1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1982-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * David Korn <dgk@research.att.com> *
18da2e3ebdSchin * *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin * David Korn
23da2e3ebdSchin * AT&T Labs
24da2e3ebdSchin *
25da2e3ebdSchin * shell deparser
26da2e3ebdSchin *
27da2e3ebdSchin */
28da2e3ebdSchin
29da2e3ebdSchin #include "defs.h"
30da2e3ebdSchin #include "shnodes.h"
31da2e3ebdSchin #include "test.h"
32da2e3ebdSchin
33da2e3ebdSchin
34da2e3ebdSchin #define HUGE_INT (((unsigned)-1)>>1)
35da2e3ebdSchin #define BEGIN 0
36da2e3ebdSchin #define MIDDLE 1
37da2e3ebdSchin #define END 2
38da2e3ebdSchin #define PRE 1
39da2e3ebdSchin #define POST 2
40da2e3ebdSchin
41da2e3ebdSchin
42da2e3ebdSchin /* flags that can be specified with p_tree() */
43da2e3ebdSchin #define NO_NEWLINE 1
44da2e3ebdSchin #define NEED_BRACE 2
45da2e3ebdSchin #define NO_BRACKET 4
46da2e3ebdSchin
47da2e3ebdSchin static void p_comlist(const struct dolnod*,int);
48da2e3ebdSchin static void p_arg(const struct argnod*, int endchar, int opts);
49da2e3ebdSchin static void p_comarg(const struct comnod*);
50da2e3ebdSchin static void p_keyword(const char*,int);
51da2e3ebdSchin static void p_redirect(const struct ionod*);
52da2e3ebdSchin static void p_switch(const struct regnod*);
53da2e3ebdSchin static void here_body(const struct ionod*);
54da2e3ebdSchin static void p_tree(const Shnode_t*,int);
55da2e3ebdSchin
56da2e3ebdSchin static int level;
57da2e3ebdSchin static int begin_line;
58da2e3ebdSchin static int end_line;
59da2e3ebdSchin static char io_op[7];
60da2e3ebdSchin static char un_op[3] = "-?";
61da2e3ebdSchin static const struct ionod *here_doc;
62da2e3ebdSchin static Sfio_t *outfile;
63da2e3ebdSchin static const char *forinit = "";
64da2e3ebdSchin
65da2e3ebdSchin extern void sh_deparse(Sfio_t*, const Shnode_t*,int);
66da2e3ebdSchin
sh_deparse(Sfio_t * out,const Shnode_t * t,int tflags)67da2e3ebdSchin void sh_deparse(Sfio_t *out, const Shnode_t *t,int tflags)
68da2e3ebdSchin {
69da2e3ebdSchin outfile = out;
70da2e3ebdSchin p_tree(t,tflags);
71da2e3ebdSchin }
72da2e3ebdSchin /*
73da2e3ebdSchin * print script corresponding to shell tree <t>
74da2e3ebdSchin */
p_tree(register const Shnode_t * t,register int tflags)75da2e3ebdSchin static void p_tree(register const Shnode_t *t,register int tflags)
76da2e3ebdSchin {
77da2e3ebdSchin register char *cp;
78da2e3ebdSchin int save = end_line;
79da2e3ebdSchin int needbrace = (tflags&NEED_BRACE);
80da2e3ebdSchin tflags &= ~NEED_BRACE;
81da2e3ebdSchin if(tflags&NO_NEWLINE)
82da2e3ebdSchin end_line = ' ';
83da2e3ebdSchin else
84da2e3ebdSchin end_line = '\n';
85da2e3ebdSchin switch(t->tre.tretyp&COMMSK)
86da2e3ebdSchin {
87da2e3ebdSchin case TTIME:
88da2e3ebdSchin if(t->tre.tretyp&COMSCAN)
89da2e3ebdSchin p_keyword("!",BEGIN);
90da2e3ebdSchin else
91da2e3ebdSchin p_keyword("time",BEGIN);
92da2e3ebdSchin if(t->par.partre)
93da2e3ebdSchin p_tree(t->par.partre,tflags);
94da2e3ebdSchin level--;
95da2e3ebdSchin break;
96da2e3ebdSchin
97da2e3ebdSchin case TCOM:
98da2e3ebdSchin if(begin_line && level>0)
99da2e3ebdSchin sfnputc(outfile,'\t',level);
100da2e3ebdSchin begin_line = 0;
101da2e3ebdSchin p_comarg((struct comnod*)t);
102da2e3ebdSchin break;
103da2e3ebdSchin
104da2e3ebdSchin case TSETIO:
105da2e3ebdSchin if(t->tre.tretyp&FPCL)
106da2e3ebdSchin tflags |= NEED_BRACE;
107da2e3ebdSchin else
108da2e3ebdSchin tflags = NO_NEWLINE|NEED_BRACE;
109da2e3ebdSchin p_tree(t->fork.forktre,tflags);
110da2e3ebdSchin p_redirect(t->fork.forkio);
111da2e3ebdSchin break;
112da2e3ebdSchin
113da2e3ebdSchin case TFORK:
114da2e3ebdSchin if(needbrace)
115da2e3ebdSchin tflags |= NEED_BRACE;
116da2e3ebdSchin if(t->tre.tretyp&(FAMP|FCOOP))
117da2e3ebdSchin {
118da2e3ebdSchin tflags = NEED_BRACE|NO_NEWLINE;
119da2e3ebdSchin end_line = ' ';
120da2e3ebdSchin }
121da2e3ebdSchin else if(t->fork.forkio)
122da2e3ebdSchin tflags = NO_NEWLINE;
123da2e3ebdSchin p_tree(t->fork.forktre,tflags);
124da2e3ebdSchin if(t->fork.forkio)
125da2e3ebdSchin p_redirect(t->fork.forkio);
126da2e3ebdSchin if(t->tre.tretyp&FCOOP)
127da2e3ebdSchin {
128da2e3ebdSchin sfputr(outfile,"|&",'\n');
129da2e3ebdSchin begin_line = 1;
130da2e3ebdSchin }
131da2e3ebdSchin else if(t->tre.tretyp&FAMP)
132da2e3ebdSchin {
133da2e3ebdSchin sfputr(outfile,"&",'\n');
134da2e3ebdSchin begin_line = 1;
135da2e3ebdSchin }
136da2e3ebdSchin break;
137da2e3ebdSchin
138da2e3ebdSchin case TIF:
139da2e3ebdSchin p_keyword("if",BEGIN);
140da2e3ebdSchin p_tree(t->if_.iftre,0);
141da2e3ebdSchin p_keyword("then",MIDDLE);
142da2e3ebdSchin p_tree(t->if_.thtre,0);
143da2e3ebdSchin if(t->if_.eltre)
144da2e3ebdSchin {
145da2e3ebdSchin p_keyword("else",MIDDLE);
146da2e3ebdSchin p_tree(t->if_.eltre,0);
147da2e3ebdSchin }
148da2e3ebdSchin p_keyword("fi",END);
149da2e3ebdSchin break;
150da2e3ebdSchin
151da2e3ebdSchin case TWH:
152da2e3ebdSchin if(t->wh.whinc)
153da2e3ebdSchin cp = "for";
154da2e3ebdSchin else if(t->tre.tretyp&COMSCAN)
155da2e3ebdSchin cp = "until";
156da2e3ebdSchin else
157da2e3ebdSchin cp = "while";
158da2e3ebdSchin p_keyword(cp,BEGIN);
159da2e3ebdSchin if(t->wh.whinc)
160da2e3ebdSchin {
161da2e3ebdSchin struct argnod *arg = (t->wh.whtre)->ar.arexpr;
162da2e3ebdSchin sfprintf(outfile,"(( %s; ",forinit);
163da2e3ebdSchin forinit = "";
164da2e3ebdSchin sfputr(outfile,arg->argval,';');
165da2e3ebdSchin arg = (t->wh.whinc)->arexpr;
166da2e3ebdSchin sfprintf(outfile," %s))\n",arg->argval);
167da2e3ebdSchin }
168da2e3ebdSchin else
169da2e3ebdSchin p_tree(t->wh.whtre,0);
170da2e3ebdSchin t = t->wh.dotre;
171da2e3ebdSchin goto dolist;
172da2e3ebdSchin
173da2e3ebdSchin case TLST:
174da2e3ebdSchin {
175da2e3ebdSchin Shnode_t *tr = t->lst.lstrit;
176da2e3ebdSchin if(tr->tre.tretyp==TWH && tr->wh.whinc && t->lst.lstlef->tre.tretyp==TARITH)
177da2e3ebdSchin {
178da2e3ebdSchin /* arithmetic for statement */
179da2e3ebdSchin struct argnod *init = (t->lst.lstlef)->ar.arexpr;
180da2e3ebdSchin forinit= init->argval;
181da2e3ebdSchin p_tree(t->lst.lstrit,tflags);
182da2e3ebdSchin break;
183da2e3ebdSchin }
184da2e3ebdSchin if(needbrace)
185da2e3ebdSchin p_keyword("{",BEGIN);
186da2e3ebdSchin p_tree(t->lst.lstlef,0);
187da2e3ebdSchin if(needbrace)
188da2e3ebdSchin tflags = 0;
189da2e3ebdSchin p_tree(t->lst.lstrit,tflags);
190da2e3ebdSchin if(needbrace)
191da2e3ebdSchin p_keyword("}",END);
192da2e3ebdSchin break;
193da2e3ebdSchin }
194da2e3ebdSchin
195da2e3ebdSchin case TAND:
196da2e3ebdSchin cp = "&&";
197da2e3ebdSchin goto andor;
198da2e3ebdSchin case TORF:
199da2e3ebdSchin cp = "||";
200da2e3ebdSchin goto andor;
201da2e3ebdSchin case TFIL:
202da2e3ebdSchin cp = "|";
203da2e3ebdSchin andor:
204da2e3ebdSchin {
205da2e3ebdSchin int bracket = 0;
206da2e3ebdSchin if(t->tre.tretyp&TTEST)
207da2e3ebdSchin {
208da2e3ebdSchin tflags |= NO_NEWLINE;
209da2e3ebdSchin if(!(tflags&NO_BRACKET))
210da2e3ebdSchin {
211da2e3ebdSchin p_keyword("[[",BEGIN);
212da2e3ebdSchin tflags |= NO_BRACKET;
213da2e3ebdSchin bracket=1;
214da2e3ebdSchin }
215da2e3ebdSchin }
216da2e3ebdSchin p_tree(t->lst.lstlef,NEED_BRACE|NO_NEWLINE|(tflags&NO_BRACKET));
217da2e3ebdSchin sfputr(outfile,cp,here_doc?'\n':' ');
218da2e3ebdSchin if(here_doc)
219da2e3ebdSchin {
220da2e3ebdSchin here_body(here_doc);
221da2e3ebdSchin here_doc = 0;
222da2e3ebdSchin }
223da2e3ebdSchin level++;
224da2e3ebdSchin p_tree(t->lst.lstrit,tflags|NEED_BRACE);
225da2e3ebdSchin if(bracket)
226da2e3ebdSchin p_keyword("]]",END);
227da2e3ebdSchin level--;
228da2e3ebdSchin break;
229da2e3ebdSchin }
230da2e3ebdSchin
231da2e3ebdSchin case TPAR:
232da2e3ebdSchin p_keyword("(",BEGIN);
233da2e3ebdSchin p_tree(t->par.partre,0);
234da2e3ebdSchin p_keyword(")",END);
235da2e3ebdSchin break;
236da2e3ebdSchin
237da2e3ebdSchin case TARITH:
238da2e3ebdSchin {
239da2e3ebdSchin register struct argnod *ap = t->ar.arexpr;
240da2e3ebdSchin if(begin_line && level)
241da2e3ebdSchin sfnputc(outfile,'\t',level);
242da2e3ebdSchin sfprintf(outfile,"(( %s ))%c",ap->argval,end_line);
243da2e3ebdSchin if(!(tflags&NO_NEWLINE))
244da2e3ebdSchin begin_line=1;
245da2e3ebdSchin break;
246da2e3ebdSchin }
247da2e3ebdSchin
248da2e3ebdSchin case TFOR:
249da2e3ebdSchin cp = ((t->tre.tretyp&COMSCAN)?"select":"for");
250da2e3ebdSchin p_keyword(cp,BEGIN);
251da2e3ebdSchin sfputr(outfile,t->for_.fornam,' ');
252da2e3ebdSchin if(t->for_.forlst)
253da2e3ebdSchin {
254da2e3ebdSchin sfputr(outfile,"in",' ');
255da2e3ebdSchin tflags = end_line;
256da2e3ebdSchin end_line = '\n';
257da2e3ebdSchin p_comarg(t->for_.forlst);
258da2e3ebdSchin end_line = tflags;
259da2e3ebdSchin }
260da2e3ebdSchin else
261da2e3ebdSchin sfputc(outfile,'\n');
262da2e3ebdSchin begin_line = 1;
263da2e3ebdSchin t = t->for_.fortre;
264da2e3ebdSchin dolist:
265da2e3ebdSchin p_keyword("do",MIDDLE);
266da2e3ebdSchin p_tree(t,0);
267da2e3ebdSchin p_keyword("done",END);
268da2e3ebdSchin break;
269da2e3ebdSchin
270da2e3ebdSchin case TSW:
271da2e3ebdSchin p_keyword("case",BEGIN);
272da2e3ebdSchin p_arg(t->sw.swarg,' ',0);
273da2e3ebdSchin if(t->sw.swlst)
274da2e3ebdSchin {
275da2e3ebdSchin begin_line = 1;
276da2e3ebdSchin sfputr(outfile,"in",'\n');
277da2e3ebdSchin tflags = end_line;
278da2e3ebdSchin end_line = '\n';
279da2e3ebdSchin p_switch(t->sw.swlst);
280da2e3ebdSchin end_line = tflags;
281da2e3ebdSchin }
282da2e3ebdSchin p_keyword("esac",END);
283da2e3ebdSchin break;
284da2e3ebdSchin
285da2e3ebdSchin case TFUN:
286da2e3ebdSchin if(t->tre.tretyp&FPOSIX)
287da2e3ebdSchin {
288da2e3ebdSchin sfprintf(outfile,"%s",t->funct.functnam);
289da2e3ebdSchin p_keyword("()\n",BEGIN);
290da2e3ebdSchin }
291da2e3ebdSchin else
292da2e3ebdSchin {
293da2e3ebdSchin p_keyword("function",BEGIN);
294da2e3ebdSchin tflags = (t->funct.functargs?' ':'\n');
295da2e3ebdSchin sfputr(outfile,t->funct.functnam,tflags);
296da2e3ebdSchin if(t->funct.functargs)
297da2e3ebdSchin {
298da2e3ebdSchin tflags = end_line;
299da2e3ebdSchin end_line = '\n';
300da2e3ebdSchin p_comarg(t->funct.functargs);
301da2e3ebdSchin end_line = tflags;
302da2e3ebdSchin }
303da2e3ebdSchin }
304da2e3ebdSchin begin_line = 1;
305da2e3ebdSchin p_keyword("{\n",MIDDLE);
306da2e3ebdSchin begin_line = 1;
307da2e3ebdSchin p_tree(t->funct.functtre,0);
308da2e3ebdSchin p_keyword("}",END);
309da2e3ebdSchin break;
310da2e3ebdSchin /* new test compound command */
311da2e3ebdSchin case TTST:
312da2e3ebdSchin if(!(tflags&NO_BRACKET))
313da2e3ebdSchin p_keyword("[[",BEGIN);
314da2e3ebdSchin if((t->tre.tretyp&TPAREN)==TPAREN)
315da2e3ebdSchin {
316da2e3ebdSchin p_keyword("(",BEGIN);
317da2e3ebdSchin p_tree(t->lst.lstlef,NO_BRACKET|NO_NEWLINE);
318da2e3ebdSchin p_keyword(")",END);
319da2e3ebdSchin }
320da2e3ebdSchin else
321da2e3ebdSchin {
322da2e3ebdSchin int flags = (t->tre.tretyp)>>TSHIFT;
323da2e3ebdSchin if(t->tre.tretyp&TNEGATE)
324da2e3ebdSchin sfputr(outfile,"!",' ');
325da2e3ebdSchin if(t->tre.tretyp&TUNARY)
326da2e3ebdSchin {
327da2e3ebdSchin un_op[1] = flags;
328da2e3ebdSchin sfputr(outfile,un_op,' ');
329da2e3ebdSchin }
330da2e3ebdSchin else
331da2e3ebdSchin cp = ((char*)(shtab_testops+(flags&037)-1)->sh_name);
332da2e3ebdSchin p_arg(&(t->lst.lstlef->arg),' ',0);
333da2e3ebdSchin if(t->tre.tretyp&TBINARY)
334da2e3ebdSchin {
335da2e3ebdSchin sfputr(outfile,cp,' ');
336da2e3ebdSchin p_arg(&(t->lst.lstrit->arg),' ',0);
337da2e3ebdSchin }
338da2e3ebdSchin }
339da2e3ebdSchin if(!(tflags&NO_BRACKET))
340da2e3ebdSchin p_keyword("]]",END);
341da2e3ebdSchin }
342da2e3ebdSchin while(begin_line && here_doc)
343da2e3ebdSchin {
344da2e3ebdSchin here_body(here_doc);
345da2e3ebdSchin here_doc = 0;
346da2e3ebdSchin }
347da2e3ebdSchin end_line = save;
348da2e3ebdSchin return;
349da2e3ebdSchin }
350da2e3ebdSchin
351da2e3ebdSchin /*
352da2e3ebdSchin * print a keyword
353da2e3ebdSchin * increment indent level for flag==BEGIN
354da2e3ebdSchin * decrement indent level for flag==END
355da2e3ebdSchin */
p_keyword(const char * word,int flag)356da2e3ebdSchin static void p_keyword(const char *word,int flag)
357da2e3ebdSchin {
358da2e3ebdSchin register int sep;
359da2e3ebdSchin if(flag==END)
360da2e3ebdSchin sep = end_line;
361da2e3ebdSchin else if(*word=='[' || *word=='(')
362da2e3ebdSchin sep = ' ';
363da2e3ebdSchin else
364da2e3ebdSchin sep = '\t';
365da2e3ebdSchin if(flag!=BEGIN)
366da2e3ebdSchin level--;
367da2e3ebdSchin if(begin_line && level)
368da2e3ebdSchin sfnputc(outfile,'\t',level);
369da2e3ebdSchin sfputr(outfile,word,sep);
370da2e3ebdSchin if(sep=='\n')
371da2e3ebdSchin begin_line=1;
372da2e3ebdSchin else
373da2e3ebdSchin begin_line=0;
374da2e3ebdSchin if(flag!=END)
375da2e3ebdSchin level++;
376da2e3ebdSchin }
377da2e3ebdSchin
p_arg(register const struct argnod * arg,register int endchar,int opts)378da2e3ebdSchin static void p_arg(register const struct argnod *arg,register int endchar,int opts)
379da2e3ebdSchin {
380da2e3ebdSchin register const char *cp;
381da2e3ebdSchin register int flag;
382da2e3ebdSchin do
383da2e3ebdSchin {
384da2e3ebdSchin if(!arg->argnxt.ap)
385da2e3ebdSchin flag = endchar;
386da2e3ebdSchin else if(opts&PRE)
387da2e3ebdSchin {
388da2e3ebdSchin /* case alternation lists in reverse order */
389da2e3ebdSchin p_arg(arg->argnxt.ap,'|',opts);
390da2e3ebdSchin flag = endchar;
391da2e3ebdSchin }
392da2e3ebdSchin else if(opts)
393da2e3ebdSchin flag = ' ';
394da2e3ebdSchin cp = arg->argval;
395da2e3ebdSchin if(*cp==0 && opts==POST && arg->argchn.ap)
396da2e3ebdSchin {
397da2e3ebdSchin /* compound assignment */
398da2e3ebdSchin struct fornod *fp=(struct fornod*)arg->argchn.ap;
399da2e3ebdSchin sfprintf(outfile,"%s=(\n",fp->fornam);
400da2e3ebdSchin sfnputc(outfile,'\t',++level);
401da2e3ebdSchin p_tree(fp->fortre,0);
402da2e3ebdSchin if(--level)
403da2e3ebdSchin sfnputc(outfile,'\t',level);
404da2e3ebdSchin sfputc(outfile,')');
405da2e3ebdSchin }
406da2e3ebdSchin else if((arg->argflag&ARG_RAW) && (cp[1] || (*cp!='[' && *cp!=']')))
407da2e3ebdSchin cp = sh_fmtq(cp);
408da2e3ebdSchin sfputr(outfile,cp,flag);
409da2e3ebdSchin if(flag=='\n')
410da2e3ebdSchin begin_line = 1;
411da2e3ebdSchin arg = arg->argnxt.ap;
412da2e3ebdSchin }
413da2e3ebdSchin while((opts&POST) && arg);
414da2e3ebdSchin return;
415da2e3ebdSchin }
416da2e3ebdSchin
p_redirect(register const struct ionod * iop)417da2e3ebdSchin static void p_redirect(register const struct ionod *iop)
418da2e3ebdSchin {
419da2e3ebdSchin register char *cp;
420da2e3ebdSchin register int iof,iof2;
421da2e3ebdSchin for(;iop;iop=iop->ionxt)
422da2e3ebdSchin {
423da2e3ebdSchin iof=iop->iofile;
424da2e3ebdSchin cp = io_op;
425da2e3ebdSchin if(iop->iovname)
426da2e3ebdSchin {
427da2e3ebdSchin sfwrite(outfile,"(;",2);
428da2e3ebdSchin sfputr(outfile,iop->iovname,')');
429da2e3ebdSchin cp++;
430da2e3ebdSchin }
431da2e3ebdSchin else
432da2e3ebdSchin *cp = '0'+(iof&IOUFD);
433da2e3ebdSchin if(iof&IOPUT)
434da2e3ebdSchin {
435da2e3ebdSchin if(*cp == '1' && !iop->iovname)
436da2e3ebdSchin cp++;
437da2e3ebdSchin io_op[1] = '>';
438da2e3ebdSchin }
439da2e3ebdSchin else
440da2e3ebdSchin {
441da2e3ebdSchin if(*cp == '0' && !iop->iovname)
442da2e3ebdSchin cp++;
443da2e3ebdSchin io_op[1] = '<';
444da2e3ebdSchin }
445da2e3ebdSchin io_op[2] = 0;
446da2e3ebdSchin io_op[3] = 0;
447da2e3ebdSchin if(iof&IOLSEEK)
448da2e3ebdSchin {
449da2e3ebdSchin io_op[1] = '#';
450da2e3ebdSchin if(iof&IOARITH)
451da2e3ebdSchin strcpy(&io_op[3]," ((");
452da2e3ebdSchin }
453da2e3ebdSchin else if(iof&IOMOV)
454da2e3ebdSchin io_op[2] = '&';
455da2e3ebdSchin else if(iof&(IORDW|IOAPP))
456da2e3ebdSchin io_op[2] = '>';
457da2e3ebdSchin else if(iof&IOCLOB)
458da2e3ebdSchin io_op[2] = '|';
459da2e3ebdSchin if(iop->iodelim)
460da2e3ebdSchin {
461da2e3ebdSchin /* here document */
462da2e3ebdSchin #ifdef xxx
463da2e3ebdSchin iop->iolink = (char*)here_doc;
464da2e3ebdSchin #endif
465da2e3ebdSchin here_doc = iop;
466da2e3ebdSchin io_op[2] = '<';
467da2e3ebdSchin #ifdef future
468da2e3ebdSchin if(iof&IOSTRIP)
469da2e3ebdSchin io_op[3] = '-';
470da2e3ebdSchin #endif
471da2e3ebdSchin }
472da2e3ebdSchin sfputr(outfile,cp,' ');
473da2e3ebdSchin if(iop->ionxt)
474da2e3ebdSchin iof = ' ';
475da2e3ebdSchin else
476da2e3ebdSchin {
477da2e3ebdSchin if((iof=end_line)=='\n')
478da2e3ebdSchin begin_line = 1;
479da2e3ebdSchin }
480da2e3ebdSchin if((iof&IOLSEEK) && (iof&IOARITH))
481da2e3ebdSchin iof2 = iof, iof = ' ';
482da2e3ebdSchin if(iop->iodelim)
483da2e3ebdSchin {
484da2e3ebdSchin if(!(iop->iofile&IODOC))
485da2e3ebdSchin sfwrite(outfile,"''",2);
486da2e3ebdSchin sfputr(outfile,sh_fmtq(iop->iodelim),iof);
487da2e3ebdSchin }
488da2e3ebdSchin else if(iop->iofile&IORAW)
489da2e3ebdSchin sfputr(outfile,sh_fmtq(iop->ioname),iof);
490da2e3ebdSchin else
491da2e3ebdSchin sfputr(outfile,iop->ioname,iof);
492da2e3ebdSchin if((iof&IOLSEEK) && (iof&IOARITH))
493da2e3ebdSchin sfputr(outfile, "))", iof2);
494da2e3ebdSchin }
495da2e3ebdSchin return;
496da2e3ebdSchin }
497da2e3ebdSchin
p_comarg(register const struct comnod * com)498da2e3ebdSchin static void p_comarg(register const struct comnod *com)
499da2e3ebdSchin {
500da2e3ebdSchin register int flag = end_line;
501da2e3ebdSchin if(com->comarg || com->comio)
502da2e3ebdSchin flag = ' ';
503da2e3ebdSchin if(com->comset)
504da2e3ebdSchin p_arg(com->comset,flag,POST);
505da2e3ebdSchin if(com->comarg)
506da2e3ebdSchin {
507da2e3ebdSchin if(!com->comio)
508da2e3ebdSchin flag = end_line;
509da2e3ebdSchin if(com->comtyp&COMSCAN)
510da2e3ebdSchin p_arg(com->comarg,flag,POST);
511da2e3ebdSchin else
512da2e3ebdSchin p_comlist((struct dolnod*)com->comarg,flag);
513da2e3ebdSchin }
514da2e3ebdSchin if(com->comio)
515da2e3ebdSchin p_redirect(com->comio);
516da2e3ebdSchin return;
517da2e3ebdSchin }
518da2e3ebdSchin
p_comlist(const struct dolnod * dol,int endchar)519da2e3ebdSchin static void p_comlist(const struct dolnod *dol,int endchar)
520da2e3ebdSchin {
521da2e3ebdSchin register char *cp, *const*argv;
522da2e3ebdSchin register int flag = ' ', special;
523da2e3ebdSchin argv = dol->dolval+ARG_SPARE;
524da2e3ebdSchin cp = *argv;
525da2e3ebdSchin special = (*cp=='[' && cp[1]==0);
526da2e3ebdSchin do
527da2e3ebdSchin {
528da2e3ebdSchin if(cp)
529da2e3ebdSchin argv++;
530da2e3ebdSchin else
531da2e3ebdSchin cp = "";
532da2e3ebdSchin if(*argv==0)
533da2e3ebdSchin {
534da2e3ebdSchin if((flag=endchar)=='\n')
535da2e3ebdSchin begin_line = 1;
536da2e3ebdSchin special = (*cp==']' && cp[1]==0);
537da2e3ebdSchin }
538da2e3ebdSchin sfputr(outfile,special?cp:sh_fmtq(cp),flag);
539da2e3ebdSchin special = 0;
540da2e3ebdSchin }
541da2e3ebdSchin while(cp = *argv);
542da2e3ebdSchin return;
543da2e3ebdSchin }
544da2e3ebdSchin
p_switch(register const struct regnod * reg)545da2e3ebdSchin static void p_switch(register const struct regnod *reg)
546da2e3ebdSchin {
547da2e3ebdSchin if(level>1)
548da2e3ebdSchin sfnputc(outfile,'\t',level-1);
549da2e3ebdSchin p_arg(reg->regptr,')',PRE);
550da2e3ebdSchin begin_line = 0;
551da2e3ebdSchin sfputc(outfile,'\t');
552da2e3ebdSchin if(reg->regcom)
553da2e3ebdSchin p_tree(reg->regcom,0);
554da2e3ebdSchin level++;
555da2e3ebdSchin if(reg->regflag)
556da2e3ebdSchin p_keyword(";&",END);
557da2e3ebdSchin else
558da2e3ebdSchin p_keyword(";;",END);
559da2e3ebdSchin if(reg->regnxt)
560da2e3ebdSchin p_switch(reg->regnxt);
561da2e3ebdSchin return;
562da2e3ebdSchin }
563da2e3ebdSchin
564da2e3ebdSchin /*
565da2e3ebdSchin * output here documents
566da2e3ebdSchin */
here_body(register const struct ionod * iop)567da2e3ebdSchin static void here_body(register const struct ionod *iop)
568da2e3ebdSchin {
569da2e3ebdSchin Sfio_t *infile;
570da2e3ebdSchin #ifdef xxx
571da2e3ebdSchin if(iop->iolink)
572da2e3ebdSchin here_body((struct inode*)iop->iolink);
573da2e3ebdSchin iop->iolink = 0;
574da2e3ebdSchin #endif
575da2e3ebdSchin if(iop->iofile&IOSTRG)
576da2e3ebdSchin infile = sfnew((Sfio_t*)0,iop->ioname,iop->iosize,-1,SF_STRING|SF_READ);
577da2e3ebdSchin else
578da2e3ebdSchin sfseek(infile=sh.heredocs,iop->iooffset,SEEK_SET);
579da2e3ebdSchin sfmove(infile,outfile,iop->iosize,-1);
580da2e3ebdSchin if(iop->iofile&IOSTRG)
581da2e3ebdSchin sfclose(infile);
582da2e3ebdSchin sfputr(outfile,iop->iodelim,'\n');
583da2e3ebdSchin }
584da2e3ebdSchin
585