1*7c356e86SAndroid Build Coastguard Worker /* $OpenBSD: tree.c,v 1.21 2015/09/01 13:12:31 tedu Exp $ */
2*7c356e86SAndroid Build Coastguard Worker
3*7c356e86SAndroid Build Coastguard Worker /*-
4*7c356e86SAndroid Build Coastguard Worker * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
5*7c356e86SAndroid Build Coastguard Worker * 2011, 2012, 2013, 2015, 2016, 2017
6*7c356e86SAndroid Build Coastguard Worker * mirabilos <[email protected]>
7*7c356e86SAndroid Build Coastguard Worker *
8*7c356e86SAndroid Build Coastguard Worker * Provided that these terms and disclaimer and all copyright notices
9*7c356e86SAndroid Build Coastguard Worker * are retained or reproduced in an accompanying document, permission
10*7c356e86SAndroid Build Coastguard Worker * is granted to deal in this work without restriction, including un-
11*7c356e86SAndroid Build Coastguard Worker * limited rights to use, publicly perform, distribute, sell, modify,
12*7c356e86SAndroid Build Coastguard Worker * merge, give away, or sublicence.
13*7c356e86SAndroid Build Coastguard Worker *
14*7c356e86SAndroid Build Coastguard Worker * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
15*7c356e86SAndroid Build Coastguard Worker * the utmost extent permitted by applicable law, neither express nor
16*7c356e86SAndroid Build Coastguard Worker * implied; without malicious intent or gross negligence. In no event
17*7c356e86SAndroid Build Coastguard Worker * may a licensor, author or contributor be held liable for indirect,
18*7c356e86SAndroid Build Coastguard Worker * direct, other damage, loss, or other issues arising in any way out
19*7c356e86SAndroid Build Coastguard Worker * of dealing in the work, even if advised of the possibility of such
20*7c356e86SAndroid Build Coastguard Worker * damage or existence of a defect, except proven that it results out
21*7c356e86SAndroid Build Coastguard Worker * of said person's immediate fault when using the work as intended.
22*7c356e86SAndroid Build Coastguard Worker */
23*7c356e86SAndroid Build Coastguard Worker
24*7c356e86SAndroid Build Coastguard Worker #include "sh.h"
25*7c356e86SAndroid Build Coastguard Worker
26*7c356e86SAndroid Build Coastguard Worker __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.100 2020/10/31 04:28:54 tg Exp $");
27*7c356e86SAndroid Build Coastguard Worker
28*7c356e86SAndroid Build Coastguard Worker #define INDENT 8
29*7c356e86SAndroid Build Coastguard Worker
30*7c356e86SAndroid Build Coastguard Worker static void ptree(struct op *, int, struct shf *);
31*7c356e86SAndroid Build Coastguard Worker static void pioact(struct shf *, struct ioword *);
32*7c356e86SAndroid Build Coastguard Worker static const char *wdvarput(struct shf *, const char *, int, int);
33*7c356e86SAndroid Build Coastguard Worker static void vfptreef(struct shf *, int, const char *, va_list);
34*7c356e86SAndroid Build Coastguard Worker static struct ioword **iocopy(struct ioword **, Area *);
35*7c356e86SAndroid Build Coastguard Worker static void iofree(struct ioword **, Area *);
36*7c356e86SAndroid Build Coastguard Worker
37*7c356e86SAndroid Build Coastguard Worker /* "foo& ; bar" and "foo |& ; bar" are invalid */
38*7c356e86SAndroid Build Coastguard Worker static bool prevent_semicolon;
39*7c356e86SAndroid Build Coastguard Worker
40*7c356e86SAndroid Build Coastguard Worker /* here document diversion */
41*7c356e86SAndroid Build Coastguard Worker static unsigned short ptree_nest;
42*7c356e86SAndroid Build Coastguard Worker static bool ptree_hashere;
43*7c356e86SAndroid Build Coastguard Worker static struct shf ptree_heredoc;
44*7c356e86SAndroid Build Coastguard Worker #define ptree_outhere(shf) do { \
45*7c356e86SAndroid Build Coastguard Worker if (ptree_hashere) { \
46*7c356e86SAndroid Build Coastguard Worker shf_puts(shf_sclose(&ptree_heredoc), (shf)); \
47*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', (shf)); \
48*7c356e86SAndroid Build Coastguard Worker ptree_hashere = false; \
49*7c356e86SAndroid Build Coastguard Worker /*prevent_semicolon = true;*/ \
50*7c356e86SAndroid Build Coastguard Worker } \
51*7c356e86SAndroid Build Coastguard Worker } while (/* CONSTCOND */ 0)
52*7c356e86SAndroid Build Coastguard Worker
53*7c356e86SAndroid Build Coastguard Worker static const char Telif_pT[] = "elif %T";
54*7c356e86SAndroid Build Coastguard Worker
55*7c356e86SAndroid Build Coastguard Worker /*
56*7c356e86SAndroid Build Coastguard Worker * print a command tree
57*7c356e86SAndroid Build Coastguard Worker */
58*7c356e86SAndroid Build Coastguard Worker static void
ptree(struct op * t,int indent,struct shf * shf)59*7c356e86SAndroid Build Coastguard Worker ptree(struct op *t, int indent, struct shf *shf)
60*7c356e86SAndroid Build Coastguard Worker {
61*7c356e86SAndroid Build Coastguard Worker const char **w;
62*7c356e86SAndroid Build Coastguard Worker struct ioword **ioact;
63*7c356e86SAndroid Build Coastguard Worker struct op *t1;
64*7c356e86SAndroid Build Coastguard Worker int i;
65*7c356e86SAndroid Build Coastguard Worker const char *ccp;
66*7c356e86SAndroid Build Coastguard Worker
67*7c356e86SAndroid Build Coastguard Worker Chain:
68*7c356e86SAndroid Build Coastguard Worker if (t == NULL)
69*7c356e86SAndroid Build Coastguard Worker return;
70*7c356e86SAndroid Build Coastguard Worker switch (t->type) {
71*7c356e86SAndroid Build Coastguard Worker case TCOM:
72*7c356e86SAndroid Build Coastguard Worker prevent_semicolon = false;
73*7c356e86SAndroid Build Coastguard Worker /* special-case 'var=<<EOF' (cf. exec.c:execute) */
74*7c356e86SAndroid Build Coastguard Worker if (t->args &&
75*7c356e86SAndroid Build Coastguard Worker /* we have zero arguments, i.e. no program to run */
76*7c356e86SAndroid Build Coastguard Worker t->args[0] == NULL &&
77*7c356e86SAndroid Build Coastguard Worker /* we have exactly one variable assignment */
78*7c356e86SAndroid Build Coastguard Worker t->vars[0] != NULL && t->vars[1] == NULL &&
79*7c356e86SAndroid Build Coastguard Worker /* we have exactly one I/O redirection */
80*7c356e86SAndroid Build Coastguard Worker t->ioact != NULL && t->ioact[0] != NULL &&
81*7c356e86SAndroid Build Coastguard Worker t->ioact[1] == NULL &&
82*7c356e86SAndroid Build Coastguard Worker /* of type "here document" (or "here string") */
83*7c356e86SAndroid Build Coastguard Worker (t->ioact[0]->ioflag & IOTYPE) == IOHERE &&
84*7c356e86SAndroid Build Coastguard Worker /* the variable assignment begins with a valid varname */
85*7c356e86SAndroid Build Coastguard Worker (ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] &&
86*7c356e86SAndroid Build Coastguard Worker /* and has no right-hand side (i.e. "varname=") */
87*7c356e86SAndroid Build Coastguard Worker ccp[0] == CHAR && ((ccp[1] == '=' && ccp[2] == EOS) ||
88*7c356e86SAndroid Build Coastguard Worker /* or "varname+=" */ (ccp[1] == '+' && ccp[2] == CHAR &&
89*7c356e86SAndroid Build Coastguard Worker ccp[3] == '=' && ccp[4] == EOS))) {
90*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, Tf_S, t->vars[0]);
91*7c356e86SAndroid Build Coastguard Worker break;
92*7c356e86SAndroid Build Coastguard Worker }
93*7c356e86SAndroid Build Coastguard Worker
94*7c356e86SAndroid Build Coastguard Worker if (t->vars) {
95*7c356e86SAndroid Build Coastguard Worker w = (const char **)t->vars;
96*7c356e86SAndroid Build Coastguard Worker while (*w)
97*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, Tf_S_, *w++);
98*7c356e86SAndroid Build Coastguard Worker }
99*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
100*7c356e86SAndroid Build Coastguard Worker else
101*7c356e86SAndroid Build Coastguard Worker shf_puts("#no-vars# ", shf);
102*7c356e86SAndroid Build Coastguard Worker #endif
103*7c356e86SAndroid Build Coastguard Worker if (t->args) {
104*7c356e86SAndroid Build Coastguard Worker w = t->args;
105*7c356e86SAndroid Build Coastguard Worker if (*w && **w == CHAR) {
106*7c356e86SAndroid Build Coastguard Worker char *cp = wdstrip(*w++, WDS_TPUTS);
107*7c356e86SAndroid Build Coastguard Worker
108*7c356e86SAndroid Build Coastguard Worker if (valid_alias_name(cp))
109*7c356e86SAndroid Build Coastguard Worker shf_putc('\\', shf);
110*7c356e86SAndroid Build Coastguard Worker shf_puts(cp, shf);
111*7c356e86SAndroid Build Coastguard Worker shf_putc(' ', shf);
112*7c356e86SAndroid Build Coastguard Worker afree(cp, ATEMP);
113*7c356e86SAndroid Build Coastguard Worker }
114*7c356e86SAndroid Build Coastguard Worker while (*w)
115*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, Tf_S_, *w++);
116*7c356e86SAndroid Build Coastguard Worker }
117*7c356e86SAndroid Build Coastguard Worker #ifndef MKSH_SMALL
118*7c356e86SAndroid Build Coastguard Worker else
119*7c356e86SAndroid Build Coastguard Worker shf_puts("#no-args# ", shf);
120*7c356e86SAndroid Build Coastguard Worker #endif
121*7c356e86SAndroid Build Coastguard Worker break;
122*7c356e86SAndroid Build Coastguard Worker case TEXEC:
123*7c356e86SAndroid Build Coastguard Worker t = t->left;
124*7c356e86SAndroid Build Coastguard Worker goto Chain;
125*7c356e86SAndroid Build Coastguard Worker case TPAREN:
126*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent + 2, "( %T) ", t->left);
127*7c356e86SAndroid Build Coastguard Worker break;
128*7c356e86SAndroid Build Coastguard Worker case TPIPE:
129*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%T| ", t->left);
130*7c356e86SAndroid Build Coastguard Worker t = t->right;
131*7c356e86SAndroid Build Coastguard Worker goto Chain;
132*7c356e86SAndroid Build Coastguard Worker case TLIST:
133*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%T%;", t->left);
134*7c356e86SAndroid Build Coastguard Worker t = t->right;
135*7c356e86SAndroid Build Coastguard Worker goto Chain;
136*7c356e86SAndroid Build Coastguard Worker case TOR:
137*7c356e86SAndroid Build Coastguard Worker case TAND:
138*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%T%s %T",
139*7c356e86SAndroid Build Coastguard Worker t->left, (t->type == TOR) ? "||" : "&&", t->right);
140*7c356e86SAndroid Build Coastguard Worker break;
141*7c356e86SAndroid Build Coastguard Worker case TBANG:
142*7c356e86SAndroid Build Coastguard Worker shf_puts("! ", shf);
143*7c356e86SAndroid Build Coastguard Worker prevent_semicolon = false;
144*7c356e86SAndroid Build Coastguard Worker t = t->right;
145*7c356e86SAndroid Build Coastguard Worker goto Chain;
146*7c356e86SAndroid Build Coastguard Worker case TDBRACKET:
147*7c356e86SAndroid Build Coastguard Worker w = t->args;
148*7c356e86SAndroid Build Coastguard Worker shf_puts("[[", shf);
149*7c356e86SAndroid Build Coastguard Worker while (*w)
150*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, Tf__S, *w++);
151*7c356e86SAndroid Build Coastguard Worker shf_puts(" ]] ", shf);
152*7c356e86SAndroid Build Coastguard Worker break;
153*7c356e86SAndroid Build Coastguard Worker case TSELECT:
154*7c356e86SAndroid Build Coastguard Worker case TFOR:
155*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%s %s ",
156*7c356e86SAndroid Build Coastguard Worker (t->type == TFOR) ? "for" : Tselect, t->str);
157*7c356e86SAndroid Build Coastguard Worker if (t->vars != NULL) {
158*7c356e86SAndroid Build Coastguard Worker shf_puts("in ", shf);
159*7c356e86SAndroid Build Coastguard Worker w = (const char **)t->vars;
160*7c356e86SAndroid Build Coastguard Worker while (*w)
161*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, Tf_S_, *w++);
162*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, Tft_end);
163*7c356e86SAndroid Build Coastguard Worker }
164*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent + INDENT, "do%N%T", t->left);
165*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%;done ");
166*7c356e86SAndroid Build Coastguard Worker break;
167*7c356e86SAndroid Build Coastguard Worker case TCASE:
168*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "case %S in", t->str);
169*7c356e86SAndroid Build Coastguard Worker for (t1 = t->left; t1 != NULL; t1 = t1->right) {
170*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%N(");
171*7c356e86SAndroid Build Coastguard Worker w = (const char **)t1->vars;
172*7c356e86SAndroid Build Coastguard Worker while (*w) {
173*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%S%c", *w,
174*7c356e86SAndroid Build Coastguard Worker (w[1] != NULL) ? '|' : ')');
175*7c356e86SAndroid Build Coastguard Worker ++w;
176*7c356e86SAndroid Build Coastguard Worker }
177*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent + INDENT, "%N%T%N;%c", t1->left,
178*7c356e86SAndroid Build Coastguard Worker t1->u.charflag);
179*7c356e86SAndroid Build Coastguard Worker }
180*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%Nesac ");
181*7c356e86SAndroid Build Coastguard Worker break;
182*7c356e86SAndroid Build Coastguard Worker case TELIF:
183*7c356e86SAndroid Build Coastguard Worker internal_errorf(TELIF_unexpected);
184*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
185*7c356e86SAndroid Build Coastguard Worker case TIF:
186*7c356e86SAndroid Build Coastguard Worker i = 2;
187*7c356e86SAndroid Build Coastguard Worker t1 = t;
188*7c356e86SAndroid Build Coastguard Worker goto process_TIF;
189*7c356e86SAndroid Build Coastguard Worker do {
190*7c356e86SAndroid Build Coastguard Worker t1 = t1->right;
191*7c356e86SAndroid Build Coastguard Worker i = 0;
192*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, Tft_end);
193*7c356e86SAndroid Build Coastguard Worker process_TIF:
194*7c356e86SAndroid Build Coastguard Worker /* 5 == strlen("elif ") */
195*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent + 5 - i, Telif_pT + i, t1->left);
196*7c356e86SAndroid Build Coastguard Worker t1 = t1->right;
197*7c356e86SAndroid Build Coastguard Worker if (t1->left != NULL) {
198*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, Tft_end);
199*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent + INDENT, "%s%N%T",
200*7c356e86SAndroid Build Coastguard Worker "then", t1->left);
201*7c356e86SAndroid Build Coastguard Worker }
202*7c356e86SAndroid Build Coastguard Worker } while (t1->right && t1->right->type == TELIF);
203*7c356e86SAndroid Build Coastguard Worker if (t1->right != NULL) {
204*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, Tft_end);
205*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent + INDENT, "%s%N%T",
206*7c356e86SAndroid Build Coastguard Worker "else", t1->right);
207*7c356e86SAndroid Build Coastguard Worker }
208*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%;fi ");
209*7c356e86SAndroid Build Coastguard Worker break;
210*7c356e86SAndroid Build Coastguard Worker case TWHILE:
211*7c356e86SAndroid Build Coastguard Worker case TUNTIL:
212*7c356e86SAndroid Build Coastguard Worker /* 6 == strlen("while "/"until ") */
213*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent + 6, Tf_s_T,
214*7c356e86SAndroid Build Coastguard Worker (t->type == TWHILE) ? "while" : "until",
215*7c356e86SAndroid Build Coastguard Worker t->left);
216*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, Tft_end);
217*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent + INDENT, "do%N%T", t->right);
218*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%;done ");
219*7c356e86SAndroid Build Coastguard Worker break;
220*7c356e86SAndroid Build Coastguard Worker case TBRACE:
221*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent + INDENT, "{%N%T", t->left);
222*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%;} ");
223*7c356e86SAndroid Build Coastguard Worker break;
224*7c356e86SAndroid Build Coastguard Worker case TCOPROC:
225*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%T|& ", t->left);
226*7c356e86SAndroid Build Coastguard Worker prevent_semicolon = true;
227*7c356e86SAndroid Build Coastguard Worker break;
228*7c356e86SAndroid Build Coastguard Worker case TASYNC:
229*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, "%T& ", t->left);
230*7c356e86SAndroid Build Coastguard Worker prevent_semicolon = true;
231*7c356e86SAndroid Build Coastguard Worker break;
232*7c356e86SAndroid Build Coastguard Worker case TFUNCT:
233*7c356e86SAndroid Build Coastguard Worker fpFUNCTf(shf, indent, tobool(t->u.ksh_func), t->str, t->left);
234*7c356e86SAndroid Build Coastguard Worker break;
235*7c356e86SAndroid Build Coastguard Worker case TTIME:
236*7c356e86SAndroid Build Coastguard Worker fptreef(shf, indent, Tf_s_T, Ttime, t->left);
237*7c356e86SAndroid Build Coastguard Worker break;
238*7c356e86SAndroid Build Coastguard Worker default:
239*7c356e86SAndroid Build Coastguard Worker shf_puts("<botch>", shf);
240*7c356e86SAndroid Build Coastguard Worker prevent_semicolon = false;
241*7c356e86SAndroid Build Coastguard Worker break;
242*7c356e86SAndroid Build Coastguard Worker }
243*7c356e86SAndroid Build Coastguard Worker if ((ioact = t->ioact) != NULL)
244*7c356e86SAndroid Build Coastguard Worker while (*ioact != NULL)
245*7c356e86SAndroid Build Coastguard Worker pioact(shf, *ioact++);
246*7c356e86SAndroid Build Coastguard Worker }
247*7c356e86SAndroid Build Coastguard Worker
248*7c356e86SAndroid Build Coastguard Worker static void
pioact(struct shf * shf,struct ioword * iop)249*7c356e86SAndroid Build Coastguard Worker pioact(struct shf *shf, struct ioword *iop)
250*7c356e86SAndroid Build Coastguard Worker {
251*7c356e86SAndroid Build Coastguard Worker unsigned short flag = iop->ioflag;
252*7c356e86SAndroid Build Coastguard Worker unsigned short type = flag & IOTYPE;
253*7c356e86SAndroid Build Coastguard Worker short expected;
254*7c356e86SAndroid Build Coastguard Worker
255*7c356e86SAndroid Build Coastguard Worker expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 :
256*7c356e86SAndroid Build Coastguard Worker (type == IOCAT || type == IOWRITE) ? 1 :
257*7c356e86SAndroid Build Coastguard Worker (type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit :
258*7c356e86SAndroid Build Coastguard Worker iop->unit + 1;
259*7c356e86SAndroid Build Coastguard Worker if (iop->unit != expected)
260*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, Tf_d, (int)iop->unit);
261*7c356e86SAndroid Build Coastguard Worker
262*7c356e86SAndroid Build Coastguard Worker switch (type) {
263*7c356e86SAndroid Build Coastguard Worker case IOREAD:
264*7c356e86SAndroid Build Coastguard Worker shf_putc('<', shf);
265*7c356e86SAndroid Build Coastguard Worker break;
266*7c356e86SAndroid Build Coastguard Worker case IOHERE:
267*7c356e86SAndroid Build Coastguard Worker if (flag & IOHERESTR) {
268*7c356e86SAndroid Build Coastguard Worker shf_puts("<<<", shf);
269*7c356e86SAndroid Build Coastguard Worker goto ioheredelim;
270*7c356e86SAndroid Build Coastguard Worker }
271*7c356e86SAndroid Build Coastguard Worker shf_puts("<<", shf);
272*7c356e86SAndroid Build Coastguard Worker if (flag & IOSKIP)
273*7c356e86SAndroid Build Coastguard Worker shf_putc('-', shf);
274*7c356e86SAndroid Build Coastguard Worker if (iop->heredoc /* nil when tracing */) {
275*7c356e86SAndroid Build Coastguard Worker /* here document diversion */
276*7c356e86SAndroid Build Coastguard Worker if (!ptree_hashere) {
277*7c356e86SAndroid Build Coastguard Worker shf_sopen(NULL, 0, SHF_WR | SHF_DYNAMIC,
278*7c356e86SAndroid Build Coastguard Worker &ptree_heredoc);
279*7c356e86SAndroid Build Coastguard Worker ptree_hashere = true;
280*7c356e86SAndroid Build Coastguard Worker }
281*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', &ptree_heredoc);
282*7c356e86SAndroid Build Coastguard Worker shf_puts(iop->heredoc, &ptree_heredoc);
283*7c356e86SAndroid Build Coastguard Worker /* iop->delim is set before iop->heredoc */
284*7c356e86SAndroid Build Coastguard Worker shf_puts(evalstr(iop->delim, 0), &ptree_heredoc);
285*7c356e86SAndroid Build Coastguard Worker }
286*7c356e86SAndroid Build Coastguard Worker ioheredelim:
287*7c356e86SAndroid Build Coastguard Worker /* delim is NULL during syntax error printing */
288*7c356e86SAndroid Build Coastguard Worker if (iop->delim && !(iop->ioflag & IONDELIM))
289*7c356e86SAndroid Build Coastguard Worker wdvarput(shf, iop->delim, 0, WDS_TPUTS);
290*7c356e86SAndroid Build Coastguard Worker break;
291*7c356e86SAndroid Build Coastguard Worker case IOCAT:
292*7c356e86SAndroid Build Coastguard Worker shf_puts(">>", shf);
293*7c356e86SAndroid Build Coastguard Worker break;
294*7c356e86SAndroid Build Coastguard Worker case IOWRITE:
295*7c356e86SAndroid Build Coastguard Worker shf_putc('>', shf);
296*7c356e86SAndroid Build Coastguard Worker if (flag & IOCLOB)
297*7c356e86SAndroid Build Coastguard Worker shf_putc('|', shf);
298*7c356e86SAndroid Build Coastguard Worker break;
299*7c356e86SAndroid Build Coastguard Worker case IORDWR:
300*7c356e86SAndroid Build Coastguard Worker shf_puts("<>", shf);
301*7c356e86SAndroid Build Coastguard Worker break;
302*7c356e86SAndroid Build Coastguard Worker case IODUP:
303*7c356e86SAndroid Build Coastguard Worker shf_puts(flag & IORDUP ? "<&" : ">&", shf);
304*7c356e86SAndroid Build Coastguard Worker break;
305*7c356e86SAndroid Build Coastguard Worker }
306*7c356e86SAndroid Build Coastguard Worker /* name is NULL for IOHERE or when printing syntax errors */
307*7c356e86SAndroid Build Coastguard Worker if (iop->ioname) {
308*7c356e86SAndroid Build Coastguard Worker if (flag & IONAMEXP)
309*7c356e86SAndroid Build Coastguard Worker print_value_quoted(shf, iop->ioname);
310*7c356e86SAndroid Build Coastguard Worker else
311*7c356e86SAndroid Build Coastguard Worker wdvarput(shf, iop->ioname, 0, WDS_TPUTS);
312*7c356e86SAndroid Build Coastguard Worker }
313*7c356e86SAndroid Build Coastguard Worker shf_putc(' ', shf);
314*7c356e86SAndroid Build Coastguard Worker prevent_semicolon = false;
315*7c356e86SAndroid Build Coastguard Worker }
316*7c356e86SAndroid Build Coastguard Worker
317*7c356e86SAndroid Build Coastguard Worker /* variant of fputs for ptreef and wdstrip */
318*7c356e86SAndroid Build Coastguard Worker static const char *
wdvarput(struct shf * shf,const char * wp,int quotelevel,int opmode)319*7c356e86SAndroid Build Coastguard Worker wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
320*7c356e86SAndroid Build Coastguard Worker {
321*7c356e86SAndroid Build Coastguard Worker int c;
322*7c356e86SAndroid Build Coastguard Worker const char *cs;
323*7c356e86SAndroid Build Coastguard Worker
324*7c356e86SAndroid Build Coastguard Worker /*-
325*7c356e86SAndroid Build Coastguard Worker * problems:
326*7c356e86SAndroid Build Coastguard Worker * `...` -> $(...)
327*7c356e86SAndroid Build Coastguard Worker * 'foo' -> "foo"
328*7c356e86SAndroid Build Coastguard Worker * x${foo:-"hi"} -> x${foo:-hi} unless WDS_TPUTS
329*7c356e86SAndroid Build Coastguard Worker * x${foo:-'hi'} -> x${foo:-hi}
330*7c356e86SAndroid Build Coastguard Worker * could change encoding to:
331*7c356e86SAndroid Build Coastguard Worker * OQUOTE ["'] ... CQUOTE ["']
332*7c356e86SAndroid Build Coastguard Worker * COMSUB [(`] ...\0 (handle $ ` \ and maybe " in `...` case)
333*7c356e86SAndroid Build Coastguard Worker */
334*7c356e86SAndroid Build Coastguard Worker while (/* CONSTCOND */ 1)
335*7c356e86SAndroid Build Coastguard Worker switch (*wp++) {
336*7c356e86SAndroid Build Coastguard Worker case EOS:
337*7c356e86SAndroid Build Coastguard Worker return (--wp);
338*7c356e86SAndroid Build Coastguard Worker case ADELIM:
339*7c356e86SAndroid Build Coastguard Worker if (ord(*wp) == ORD(/*{*/ '}')) {
340*7c356e86SAndroid Build Coastguard Worker ++wp;
341*7c356e86SAndroid Build Coastguard Worker goto wdvarput_csubst;
342*7c356e86SAndroid Build Coastguard Worker }
343*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
344*7c356e86SAndroid Build Coastguard Worker case CHAR:
345*7c356e86SAndroid Build Coastguard Worker c = ord(*wp++);
346*7c356e86SAndroid Build Coastguard Worker shf_putc(c, shf);
347*7c356e86SAndroid Build Coastguard Worker break;
348*7c356e86SAndroid Build Coastguard Worker case QCHAR:
349*7c356e86SAndroid Build Coastguard Worker c = ord(*wp++);
350*7c356e86SAndroid Build Coastguard Worker if (opmode & WDS_TPUTS)
351*7c356e86SAndroid Build Coastguard Worker switch (c) {
352*7c356e86SAndroid Build Coastguard Worker default:
353*7c356e86SAndroid Build Coastguard Worker if (quotelevel == 0)
354*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
355*7c356e86SAndroid Build Coastguard Worker case ORD('"'):
356*7c356e86SAndroid Build Coastguard Worker case ORD('`'):
357*7c356e86SAndroid Build Coastguard Worker case ORD('$'):
358*7c356e86SAndroid Build Coastguard Worker case ORD('\\'):
359*7c356e86SAndroid Build Coastguard Worker shf_putc(ORD('\\'), shf);
360*7c356e86SAndroid Build Coastguard Worker break;
361*7c356e86SAndroid Build Coastguard Worker }
362*7c356e86SAndroid Build Coastguard Worker shf_putc(c, shf);
363*7c356e86SAndroid Build Coastguard Worker break;
364*7c356e86SAndroid Build Coastguard Worker case COMASUB:
365*7c356e86SAndroid Build Coastguard Worker case COMSUB:
366*7c356e86SAndroid Build Coastguard Worker shf_puts("$(", shf);
367*7c356e86SAndroid Build Coastguard Worker cs = ")";
368*7c356e86SAndroid Build Coastguard Worker if (ord(*wp) == ORD('(' /*)*/))
369*7c356e86SAndroid Build Coastguard Worker shf_putc(' ', shf);
370*7c356e86SAndroid Build Coastguard Worker pSUB:
371*7c356e86SAndroid Build Coastguard Worker while ((c = *wp++) != 0)
372*7c356e86SAndroid Build Coastguard Worker shf_putc(c, shf);
373*7c356e86SAndroid Build Coastguard Worker shf_puts(cs, shf);
374*7c356e86SAndroid Build Coastguard Worker break;
375*7c356e86SAndroid Build Coastguard Worker case FUNASUB:
376*7c356e86SAndroid Build Coastguard Worker case FUNSUB:
377*7c356e86SAndroid Build Coastguard Worker c = ORD(' ');
378*7c356e86SAndroid Build Coastguard Worker if (0)
379*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
380*7c356e86SAndroid Build Coastguard Worker case VALSUB:
381*7c356e86SAndroid Build Coastguard Worker c = ORD('|');
382*7c356e86SAndroid Build Coastguard Worker shf_putc('$', shf);
383*7c356e86SAndroid Build Coastguard Worker shf_putc('{', shf);
384*7c356e86SAndroid Build Coastguard Worker shf_putc(c, shf);
385*7c356e86SAndroid Build Coastguard Worker cs = ";}";
386*7c356e86SAndroid Build Coastguard Worker goto pSUB;
387*7c356e86SAndroid Build Coastguard Worker case EXPRSUB:
388*7c356e86SAndroid Build Coastguard Worker shf_puts("$((", shf);
389*7c356e86SAndroid Build Coastguard Worker cs = "))";
390*7c356e86SAndroid Build Coastguard Worker goto pSUB;
391*7c356e86SAndroid Build Coastguard Worker case OQUOTE:
392*7c356e86SAndroid Build Coastguard Worker if (opmode & WDS_TPUTS) {
393*7c356e86SAndroid Build Coastguard Worker quotelevel++;
394*7c356e86SAndroid Build Coastguard Worker shf_putc('"', shf);
395*7c356e86SAndroid Build Coastguard Worker }
396*7c356e86SAndroid Build Coastguard Worker break;
397*7c356e86SAndroid Build Coastguard Worker case CQUOTE:
398*7c356e86SAndroid Build Coastguard Worker if (opmode & WDS_TPUTS) {
399*7c356e86SAndroid Build Coastguard Worker if (quotelevel)
400*7c356e86SAndroid Build Coastguard Worker quotelevel--;
401*7c356e86SAndroid Build Coastguard Worker shf_putc('"', shf);
402*7c356e86SAndroid Build Coastguard Worker }
403*7c356e86SAndroid Build Coastguard Worker break;
404*7c356e86SAndroid Build Coastguard Worker case OSUBST:
405*7c356e86SAndroid Build Coastguard Worker shf_putc('$', shf);
406*7c356e86SAndroid Build Coastguard Worker if (ord(*wp++) == ORD('{'))
407*7c356e86SAndroid Build Coastguard Worker shf_putc('{', shf);
408*7c356e86SAndroid Build Coastguard Worker while ((c = *wp++) != 0)
409*7c356e86SAndroid Build Coastguard Worker shf_putc(c, shf);
410*7c356e86SAndroid Build Coastguard Worker wp = wdvarput(shf, wp, 0, opmode);
411*7c356e86SAndroid Build Coastguard Worker break;
412*7c356e86SAndroid Build Coastguard Worker case CSUBST:
413*7c356e86SAndroid Build Coastguard Worker if (ord(*wp++) == ORD('}')) {
414*7c356e86SAndroid Build Coastguard Worker wdvarput_csubst:
415*7c356e86SAndroid Build Coastguard Worker shf_putc('}', shf);
416*7c356e86SAndroid Build Coastguard Worker }
417*7c356e86SAndroid Build Coastguard Worker return (wp);
418*7c356e86SAndroid Build Coastguard Worker case OPAT:
419*7c356e86SAndroid Build Coastguard Worker shf_putchar(*wp++, shf);
420*7c356e86SAndroid Build Coastguard Worker shf_putc('(', shf);
421*7c356e86SAndroid Build Coastguard Worker break;
422*7c356e86SAndroid Build Coastguard Worker case SPAT:
423*7c356e86SAndroid Build Coastguard Worker c = ORD('|');
424*7c356e86SAndroid Build Coastguard Worker if (0)
425*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
426*7c356e86SAndroid Build Coastguard Worker case CPAT:
427*7c356e86SAndroid Build Coastguard Worker c = ORD(/*(*/ ')');
428*7c356e86SAndroid Build Coastguard Worker shf_putc(c, shf);
429*7c356e86SAndroid Build Coastguard Worker break;
430*7c356e86SAndroid Build Coastguard Worker }
431*7c356e86SAndroid Build Coastguard Worker }
432*7c356e86SAndroid Build Coastguard Worker
433*7c356e86SAndroid Build Coastguard Worker /*
434*7c356e86SAndroid Build Coastguard Worker * this is the _only_ way to reliably handle
435*7c356e86SAndroid Build Coastguard Worker * variable args with an ANSI compiler
436*7c356e86SAndroid Build Coastguard Worker */
437*7c356e86SAndroid Build Coastguard Worker /* VARARGS */
438*7c356e86SAndroid Build Coastguard Worker void
fptreef(struct shf * shf,int indent,const char * fmt,...)439*7c356e86SAndroid Build Coastguard Worker fptreef(struct shf *shf, int indent, const char *fmt, ...)
440*7c356e86SAndroid Build Coastguard Worker {
441*7c356e86SAndroid Build Coastguard Worker va_list va;
442*7c356e86SAndroid Build Coastguard Worker
443*7c356e86SAndroid Build Coastguard Worker va_start(va, fmt);
444*7c356e86SAndroid Build Coastguard Worker vfptreef(shf, indent, fmt, va);
445*7c356e86SAndroid Build Coastguard Worker va_end(va);
446*7c356e86SAndroid Build Coastguard Worker }
447*7c356e86SAndroid Build Coastguard Worker
448*7c356e86SAndroid Build Coastguard Worker /* VARARGS */
449*7c356e86SAndroid Build Coastguard Worker char *
snptreef(char * s,ssize_t n,const char * fmt,...)450*7c356e86SAndroid Build Coastguard Worker snptreef(char *s, ssize_t n, const char *fmt, ...)
451*7c356e86SAndroid Build Coastguard Worker {
452*7c356e86SAndroid Build Coastguard Worker va_list va;
453*7c356e86SAndroid Build Coastguard Worker struct shf shf;
454*7c356e86SAndroid Build Coastguard Worker
455*7c356e86SAndroid Build Coastguard Worker shf_sopen(s, n, SHF_WR | (s ? 0 : SHF_DYNAMIC), &shf);
456*7c356e86SAndroid Build Coastguard Worker
457*7c356e86SAndroid Build Coastguard Worker va_start(va, fmt);
458*7c356e86SAndroid Build Coastguard Worker vfptreef(&shf, 0, fmt, va);
459*7c356e86SAndroid Build Coastguard Worker va_end(va);
460*7c356e86SAndroid Build Coastguard Worker
461*7c356e86SAndroid Build Coastguard Worker /* shf_sclose NUL terminates */
462*7c356e86SAndroid Build Coastguard Worker return (shf_sclose(&shf));
463*7c356e86SAndroid Build Coastguard Worker }
464*7c356e86SAndroid Build Coastguard Worker
465*7c356e86SAndroid Build Coastguard Worker static void
vfptreef(struct shf * shf,int indent,const char * fmt,va_list va)466*7c356e86SAndroid Build Coastguard Worker vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
467*7c356e86SAndroid Build Coastguard Worker {
468*7c356e86SAndroid Build Coastguard Worker int c;
469*7c356e86SAndroid Build Coastguard Worker
470*7c356e86SAndroid Build Coastguard Worker if (!ptree_nest++)
471*7c356e86SAndroid Build Coastguard Worker ptree_hashere = false;
472*7c356e86SAndroid Build Coastguard Worker
473*7c356e86SAndroid Build Coastguard Worker while ((c = ord(*fmt++))) {
474*7c356e86SAndroid Build Coastguard Worker if (c == '%') {
475*7c356e86SAndroid Build Coastguard Worker switch ((c = ord(*fmt++))) {
476*7c356e86SAndroid Build Coastguard Worker case ORD('c'):
477*7c356e86SAndroid Build Coastguard Worker /* character (octet, probably) */
478*7c356e86SAndroid Build Coastguard Worker shf_putchar(va_arg(va, int), shf);
479*7c356e86SAndroid Build Coastguard Worker break;
480*7c356e86SAndroid Build Coastguard Worker case ORD('s'):
481*7c356e86SAndroid Build Coastguard Worker /* string */
482*7c356e86SAndroid Build Coastguard Worker shf_puts(va_arg(va, char *), shf);
483*7c356e86SAndroid Build Coastguard Worker break;
484*7c356e86SAndroid Build Coastguard Worker case ORD('S'):
485*7c356e86SAndroid Build Coastguard Worker /* word */
486*7c356e86SAndroid Build Coastguard Worker wdvarput(shf, va_arg(va, char *), 0, WDS_TPUTS);
487*7c356e86SAndroid Build Coastguard Worker break;
488*7c356e86SAndroid Build Coastguard Worker case ORD('d'):
489*7c356e86SAndroid Build Coastguard Worker /* signed decimal */
490*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, Tf_d, va_arg(va, int));
491*7c356e86SAndroid Build Coastguard Worker break;
492*7c356e86SAndroid Build Coastguard Worker case ORD('u'):
493*7c356e86SAndroid Build Coastguard Worker /* unsigned decimal */
494*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, "%u", va_arg(va, unsigned int));
495*7c356e86SAndroid Build Coastguard Worker break;
496*7c356e86SAndroid Build Coastguard Worker case ORD('T'):
497*7c356e86SAndroid Build Coastguard Worker /* format tree */
498*7c356e86SAndroid Build Coastguard Worker ptree(va_arg(va, struct op *), indent, shf);
499*7c356e86SAndroid Build Coastguard Worker goto dont_trash_prevent_semicolon;
500*7c356e86SAndroid Build Coastguard Worker case ORD(';'):
501*7c356e86SAndroid Build Coastguard Worker /* newline or ; */
502*7c356e86SAndroid Build Coastguard Worker case ORD('N'):
503*7c356e86SAndroid Build Coastguard Worker /* newline or space */
504*7c356e86SAndroid Build Coastguard Worker if (shf->flags & SHF_STRING) {
505*7c356e86SAndroid Build Coastguard Worker if ((unsigned int)c == ORD(';') &&
506*7c356e86SAndroid Build Coastguard Worker !prevent_semicolon)
507*7c356e86SAndroid Build Coastguard Worker shf_putc(';', shf);
508*7c356e86SAndroid Build Coastguard Worker shf_putc(' ', shf);
509*7c356e86SAndroid Build Coastguard Worker } else {
510*7c356e86SAndroid Build Coastguard Worker int i = indent;
511*7c356e86SAndroid Build Coastguard Worker
512*7c356e86SAndroid Build Coastguard Worker ptree_outhere(shf);
513*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', shf);
514*7c356e86SAndroid Build Coastguard Worker while (i >= 8) {
515*7c356e86SAndroid Build Coastguard Worker shf_putc('\t', shf);
516*7c356e86SAndroid Build Coastguard Worker i -= 8;
517*7c356e86SAndroid Build Coastguard Worker }
518*7c356e86SAndroid Build Coastguard Worker while (i--)
519*7c356e86SAndroid Build Coastguard Worker shf_putc(' ', shf);
520*7c356e86SAndroid Build Coastguard Worker }
521*7c356e86SAndroid Build Coastguard Worker break;
522*7c356e86SAndroid Build Coastguard Worker case ORD('R'):
523*7c356e86SAndroid Build Coastguard Worker /* I/O redirection */
524*7c356e86SAndroid Build Coastguard Worker pioact(shf, va_arg(va, struct ioword *));
525*7c356e86SAndroid Build Coastguard Worker break;
526*7c356e86SAndroid Build Coastguard Worker default:
527*7c356e86SAndroid Build Coastguard Worker shf_putc(c, shf);
528*7c356e86SAndroid Build Coastguard Worker break;
529*7c356e86SAndroid Build Coastguard Worker }
530*7c356e86SAndroid Build Coastguard Worker } else
531*7c356e86SAndroid Build Coastguard Worker shf_putc(c, shf);
532*7c356e86SAndroid Build Coastguard Worker prevent_semicolon = false;
533*7c356e86SAndroid Build Coastguard Worker dont_trash_prevent_semicolon:
534*7c356e86SAndroid Build Coastguard Worker ;
535*7c356e86SAndroid Build Coastguard Worker }
536*7c356e86SAndroid Build Coastguard Worker
537*7c356e86SAndroid Build Coastguard Worker if (!--ptree_nest)
538*7c356e86SAndroid Build Coastguard Worker ptree_outhere(shf);
539*7c356e86SAndroid Build Coastguard Worker }
540*7c356e86SAndroid Build Coastguard Worker
541*7c356e86SAndroid Build Coastguard Worker /*
542*7c356e86SAndroid Build Coastguard Worker * copy tree (for function definition)
543*7c356e86SAndroid Build Coastguard Worker */
544*7c356e86SAndroid Build Coastguard Worker struct op *
tcopy(struct op * t,Area * ap)545*7c356e86SAndroid Build Coastguard Worker tcopy(struct op *t, Area *ap)
546*7c356e86SAndroid Build Coastguard Worker {
547*7c356e86SAndroid Build Coastguard Worker struct op *r;
548*7c356e86SAndroid Build Coastguard Worker const char **tw;
549*7c356e86SAndroid Build Coastguard Worker char **rw;
550*7c356e86SAndroid Build Coastguard Worker
551*7c356e86SAndroid Build Coastguard Worker if (t == NULL)
552*7c356e86SAndroid Build Coastguard Worker return (NULL);
553*7c356e86SAndroid Build Coastguard Worker
554*7c356e86SAndroid Build Coastguard Worker r = alloc(sizeof(struct op), ap);
555*7c356e86SAndroid Build Coastguard Worker
556*7c356e86SAndroid Build Coastguard Worker r->type = t->type;
557*7c356e86SAndroid Build Coastguard Worker r->u.evalflags = t->u.evalflags;
558*7c356e86SAndroid Build Coastguard Worker
559*7c356e86SAndroid Build Coastguard Worker if (t->type == TCASE)
560*7c356e86SAndroid Build Coastguard Worker r->str = wdcopy(t->str, ap);
561*7c356e86SAndroid Build Coastguard Worker else
562*7c356e86SAndroid Build Coastguard Worker strdupx(r->str, t->str, ap);
563*7c356e86SAndroid Build Coastguard Worker
564*7c356e86SAndroid Build Coastguard Worker if (t->vars == NULL)
565*7c356e86SAndroid Build Coastguard Worker r->vars = NULL;
566*7c356e86SAndroid Build Coastguard Worker else {
567*7c356e86SAndroid Build Coastguard Worker tw = (const char **)t->vars;
568*7c356e86SAndroid Build Coastguard Worker while (*tw)
569*7c356e86SAndroid Build Coastguard Worker ++tw;
570*7c356e86SAndroid Build Coastguard Worker rw = r->vars = alloc2(tw - (const char **)t->vars + 1,
571*7c356e86SAndroid Build Coastguard Worker sizeof(*tw), ap);
572*7c356e86SAndroid Build Coastguard Worker tw = (const char **)t->vars;
573*7c356e86SAndroid Build Coastguard Worker while (*tw)
574*7c356e86SAndroid Build Coastguard Worker *rw++ = wdcopy(*tw++, ap);
575*7c356e86SAndroid Build Coastguard Worker *rw = NULL;
576*7c356e86SAndroid Build Coastguard Worker }
577*7c356e86SAndroid Build Coastguard Worker
578*7c356e86SAndroid Build Coastguard Worker if (t->args == NULL)
579*7c356e86SAndroid Build Coastguard Worker r->args = NULL;
580*7c356e86SAndroid Build Coastguard Worker else {
581*7c356e86SAndroid Build Coastguard Worker tw = t->args;
582*7c356e86SAndroid Build Coastguard Worker while (*tw)
583*7c356e86SAndroid Build Coastguard Worker ++tw;
584*7c356e86SAndroid Build Coastguard Worker r->args = (const char **)(rw = alloc2(tw - t->args + 1,
585*7c356e86SAndroid Build Coastguard Worker sizeof(*tw), ap));
586*7c356e86SAndroid Build Coastguard Worker tw = t->args;
587*7c356e86SAndroid Build Coastguard Worker while (*tw)
588*7c356e86SAndroid Build Coastguard Worker *rw++ = wdcopy(*tw++, ap);
589*7c356e86SAndroid Build Coastguard Worker *rw = NULL;
590*7c356e86SAndroid Build Coastguard Worker }
591*7c356e86SAndroid Build Coastguard Worker
592*7c356e86SAndroid Build Coastguard Worker r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap);
593*7c356e86SAndroid Build Coastguard Worker
594*7c356e86SAndroid Build Coastguard Worker r->left = tcopy(t->left, ap);
595*7c356e86SAndroid Build Coastguard Worker r->right = tcopy(t->right, ap);
596*7c356e86SAndroid Build Coastguard Worker r->lineno = t->lineno;
597*7c356e86SAndroid Build Coastguard Worker
598*7c356e86SAndroid Build Coastguard Worker return (r);
599*7c356e86SAndroid Build Coastguard Worker }
600*7c356e86SAndroid Build Coastguard Worker
601*7c356e86SAndroid Build Coastguard Worker char *
wdcopy(const char * wp,Area * ap)602*7c356e86SAndroid Build Coastguard Worker wdcopy(const char *wp, Area *ap)
603*7c356e86SAndroid Build Coastguard Worker {
604*7c356e86SAndroid Build Coastguard Worker size_t len;
605*7c356e86SAndroid Build Coastguard Worker
606*7c356e86SAndroid Build Coastguard Worker len = wdscan(wp, EOS) - wp;
607*7c356e86SAndroid Build Coastguard Worker return (memcpy(alloc(len, ap), wp, len));
608*7c356e86SAndroid Build Coastguard Worker }
609*7c356e86SAndroid Build Coastguard Worker
610*7c356e86SAndroid Build Coastguard Worker /* return the position of prefix c in wp plus 1 */
611*7c356e86SAndroid Build Coastguard Worker const char *
wdscan(const char * wp,int c)612*7c356e86SAndroid Build Coastguard Worker wdscan(const char *wp, int c)
613*7c356e86SAndroid Build Coastguard Worker {
614*7c356e86SAndroid Build Coastguard Worker int nest = 0;
615*7c356e86SAndroid Build Coastguard Worker
616*7c356e86SAndroid Build Coastguard Worker while (/* CONSTCOND */ 1)
617*7c356e86SAndroid Build Coastguard Worker switch (*wp++) {
618*7c356e86SAndroid Build Coastguard Worker case EOS:
619*7c356e86SAndroid Build Coastguard Worker return (wp);
620*7c356e86SAndroid Build Coastguard Worker case ADELIM:
621*7c356e86SAndroid Build Coastguard Worker if (c == ADELIM && nest == 0)
622*7c356e86SAndroid Build Coastguard Worker return (wp + 1);
623*7c356e86SAndroid Build Coastguard Worker if (ord(*wp) == ORD(/*{*/ '}'))
624*7c356e86SAndroid Build Coastguard Worker goto wdscan_csubst;
625*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
626*7c356e86SAndroid Build Coastguard Worker case CHAR:
627*7c356e86SAndroid Build Coastguard Worker case QCHAR:
628*7c356e86SAndroid Build Coastguard Worker wp++;
629*7c356e86SAndroid Build Coastguard Worker break;
630*7c356e86SAndroid Build Coastguard Worker case COMASUB:
631*7c356e86SAndroid Build Coastguard Worker case COMSUB:
632*7c356e86SAndroid Build Coastguard Worker case FUNASUB:
633*7c356e86SAndroid Build Coastguard Worker case FUNSUB:
634*7c356e86SAndroid Build Coastguard Worker case VALSUB:
635*7c356e86SAndroid Build Coastguard Worker case EXPRSUB:
636*7c356e86SAndroid Build Coastguard Worker while (*wp++ != 0)
637*7c356e86SAndroid Build Coastguard Worker ;
638*7c356e86SAndroid Build Coastguard Worker break;
639*7c356e86SAndroid Build Coastguard Worker case OQUOTE:
640*7c356e86SAndroid Build Coastguard Worker case CQUOTE:
641*7c356e86SAndroid Build Coastguard Worker break;
642*7c356e86SAndroid Build Coastguard Worker case OSUBST:
643*7c356e86SAndroid Build Coastguard Worker nest++;
644*7c356e86SAndroid Build Coastguard Worker while (*wp++ != '\0')
645*7c356e86SAndroid Build Coastguard Worker ;
646*7c356e86SAndroid Build Coastguard Worker break;
647*7c356e86SAndroid Build Coastguard Worker case CSUBST:
648*7c356e86SAndroid Build Coastguard Worker wdscan_csubst:
649*7c356e86SAndroid Build Coastguard Worker wp++;
650*7c356e86SAndroid Build Coastguard Worker if (c == CSUBST && nest == 0)
651*7c356e86SAndroid Build Coastguard Worker return (wp);
652*7c356e86SAndroid Build Coastguard Worker nest--;
653*7c356e86SAndroid Build Coastguard Worker break;
654*7c356e86SAndroid Build Coastguard Worker case OPAT:
655*7c356e86SAndroid Build Coastguard Worker nest++;
656*7c356e86SAndroid Build Coastguard Worker wp++;
657*7c356e86SAndroid Build Coastguard Worker break;
658*7c356e86SAndroid Build Coastguard Worker case SPAT:
659*7c356e86SAndroid Build Coastguard Worker case CPAT:
660*7c356e86SAndroid Build Coastguard Worker if (c == wp[-1] && nest == 0)
661*7c356e86SAndroid Build Coastguard Worker return (wp);
662*7c356e86SAndroid Build Coastguard Worker if (wp[-1] == CPAT)
663*7c356e86SAndroid Build Coastguard Worker nest--;
664*7c356e86SAndroid Build Coastguard Worker break;
665*7c356e86SAndroid Build Coastguard Worker default:
666*7c356e86SAndroid Build Coastguard Worker internal_warningf(
667*7c356e86SAndroid Build Coastguard Worker "wdscan: unknown char 0x%X (carrying on)",
668*7c356e86SAndroid Build Coastguard Worker (unsigned char)wp[-1]);
669*7c356e86SAndroid Build Coastguard Worker }
670*7c356e86SAndroid Build Coastguard Worker }
671*7c356e86SAndroid Build Coastguard Worker
672*7c356e86SAndroid Build Coastguard Worker /*
673*7c356e86SAndroid Build Coastguard Worker * return a copy of wp without any of the mark up characters and with
674*7c356e86SAndroid Build Coastguard Worker * quote characters (" ' \) stripped. (string is allocated from ATEMP)
675*7c356e86SAndroid Build Coastguard Worker */
676*7c356e86SAndroid Build Coastguard Worker char *
wdstrip(const char * wp,int opmode)677*7c356e86SAndroid Build Coastguard Worker wdstrip(const char *wp, int opmode)
678*7c356e86SAndroid Build Coastguard Worker {
679*7c356e86SAndroid Build Coastguard Worker struct shf shf;
680*7c356e86SAndroid Build Coastguard Worker
681*7c356e86SAndroid Build Coastguard Worker shf_sopen(NULL, 32, SHF_WR | SHF_DYNAMIC, &shf);
682*7c356e86SAndroid Build Coastguard Worker wdvarput(&shf, wp, 0, opmode);
683*7c356e86SAndroid Build Coastguard Worker /* shf_sclose NUL terminates */
684*7c356e86SAndroid Build Coastguard Worker return (shf_sclose(&shf));
685*7c356e86SAndroid Build Coastguard Worker }
686*7c356e86SAndroid Build Coastguard Worker
687*7c356e86SAndroid Build Coastguard Worker static struct ioword **
iocopy(struct ioword ** iow,Area * ap)688*7c356e86SAndroid Build Coastguard Worker iocopy(struct ioword **iow, Area *ap)
689*7c356e86SAndroid Build Coastguard Worker {
690*7c356e86SAndroid Build Coastguard Worker struct ioword **ior;
691*7c356e86SAndroid Build Coastguard Worker int i;
692*7c356e86SAndroid Build Coastguard Worker
693*7c356e86SAndroid Build Coastguard Worker ior = iow;
694*7c356e86SAndroid Build Coastguard Worker while (*ior)
695*7c356e86SAndroid Build Coastguard Worker ++ior;
696*7c356e86SAndroid Build Coastguard Worker ior = alloc2(ior - iow + 1, sizeof(struct ioword *), ap);
697*7c356e86SAndroid Build Coastguard Worker
698*7c356e86SAndroid Build Coastguard Worker for (i = 0; iow[i] != NULL; i++) {
699*7c356e86SAndroid Build Coastguard Worker struct ioword *p, *q;
700*7c356e86SAndroid Build Coastguard Worker
701*7c356e86SAndroid Build Coastguard Worker p = iow[i];
702*7c356e86SAndroid Build Coastguard Worker q = alloc(sizeof(struct ioword), ap);
703*7c356e86SAndroid Build Coastguard Worker ior[i] = q;
704*7c356e86SAndroid Build Coastguard Worker *q = *p;
705*7c356e86SAndroid Build Coastguard Worker if (p->ioname != NULL)
706*7c356e86SAndroid Build Coastguard Worker q->ioname = wdcopy(p->ioname, ap);
707*7c356e86SAndroid Build Coastguard Worker if (p->delim != NULL)
708*7c356e86SAndroid Build Coastguard Worker q->delim = wdcopy(p->delim, ap);
709*7c356e86SAndroid Build Coastguard Worker if (p->heredoc != NULL)
710*7c356e86SAndroid Build Coastguard Worker strdupx(q->heredoc, p->heredoc, ap);
711*7c356e86SAndroid Build Coastguard Worker }
712*7c356e86SAndroid Build Coastguard Worker ior[i] = NULL;
713*7c356e86SAndroid Build Coastguard Worker
714*7c356e86SAndroid Build Coastguard Worker return (ior);
715*7c356e86SAndroid Build Coastguard Worker }
716*7c356e86SAndroid Build Coastguard Worker
717*7c356e86SAndroid Build Coastguard Worker /*
718*7c356e86SAndroid Build Coastguard Worker * free tree (for function definition)
719*7c356e86SAndroid Build Coastguard Worker */
720*7c356e86SAndroid Build Coastguard Worker void
tfree(struct op * t,Area * ap)721*7c356e86SAndroid Build Coastguard Worker tfree(struct op *t, Area *ap)
722*7c356e86SAndroid Build Coastguard Worker {
723*7c356e86SAndroid Build Coastguard Worker char **w;
724*7c356e86SAndroid Build Coastguard Worker
725*7c356e86SAndroid Build Coastguard Worker if (t == NULL)
726*7c356e86SAndroid Build Coastguard Worker return;
727*7c356e86SAndroid Build Coastguard Worker
728*7c356e86SAndroid Build Coastguard Worker afree(t->str, ap);
729*7c356e86SAndroid Build Coastguard Worker
730*7c356e86SAndroid Build Coastguard Worker if (t->vars != NULL) {
731*7c356e86SAndroid Build Coastguard Worker for (w = t->vars; *w != NULL; w++)
732*7c356e86SAndroid Build Coastguard Worker afree(*w, ap);
733*7c356e86SAndroid Build Coastguard Worker afree(t->vars, ap);
734*7c356e86SAndroid Build Coastguard Worker }
735*7c356e86SAndroid Build Coastguard Worker
736*7c356e86SAndroid Build Coastguard Worker if (t->args != NULL) {
737*7c356e86SAndroid Build Coastguard Worker /*XXX we assume the caller is right */
738*7c356e86SAndroid Build Coastguard Worker union mksh_ccphack cw;
739*7c356e86SAndroid Build Coastguard Worker
740*7c356e86SAndroid Build Coastguard Worker cw.ro = t->args;
741*7c356e86SAndroid Build Coastguard Worker for (w = cw.rw; *w != NULL; w++)
742*7c356e86SAndroid Build Coastguard Worker afree(*w, ap);
743*7c356e86SAndroid Build Coastguard Worker afree(t->args, ap);
744*7c356e86SAndroid Build Coastguard Worker }
745*7c356e86SAndroid Build Coastguard Worker
746*7c356e86SAndroid Build Coastguard Worker if (t->ioact != NULL)
747*7c356e86SAndroid Build Coastguard Worker iofree(t->ioact, ap);
748*7c356e86SAndroid Build Coastguard Worker
749*7c356e86SAndroid Build Coastguard Worker tfree(t->left, ap);
750*7c356e86SAndroid Build Coastguard Worker tfree(t->right, ap);
751*7c356e86SAndroid Build Coastguard Worker
752*7c356e86SAndroid Build Coastguard Worker afree(t, ap);
753*7c356e86SAndroid Build Coastguard Worker }
754*7c356e86SAndroid Build Coastguard Worker
755*7c356e86SAndroid Build Coastguard Worker static void
iofree(struct ioword ** iow,Area * ap)756*7c356e86SAndroid Build Coastguard Worker iofree(struct ioword **iow, Area *ap)
757*7c356e86SAndroid Build Coastguard Worker {
758*7c356e86SAndroid Build Coastguard Worker struct ioword **iop;
759*7c356e86SAndroid Build Coastguard Worker struct ioword *p;
760*7c356e86SAndroid Build Coastguard Worker
761*7c356e86SAndroid Build Coastguard Worker iop = iow;
762*7c356e86SAndroid Build Coastguard Worker while ((p = *iop++) != NULL) {
763*7c356e86SAndroid Build Coastguard Worker afree(p->ioname, ap);
764*7c356e86SAndroid Build Coastguard Worker afree(p->delim, ap);
765*7c356e86SAndroid Build Coastguard Worker afree(p->heredoc, ap);
766*7c356e86SAndroid Build Coastguard Worker afree(p, ap);
767*7c356e86SAndroid Build Coastguard Worker }
768*7c356e86SAndroid Build Coastguard Worker afree(iow, ap);
769*7c356e86SAndroid Build Coastguard Worker }
770*7c356e86SAndroid Build Coastguard Worker
771*7c356e86SAndroid Build Coastguard Worker void
fpFUNCTf(struct shf * shf,int i,bool isksh,const char * k,struct op * v)772*7c356e86SAndroid Build Coastguard Worker fpFUNCTf(struct shf *shf, int i, bool isksh, const char *k, struct op *v)
773*7c356e86SAndroid Build Coastguard Worker {
774*7c356e86SAndroid Build Coastguard Worker if (isksh)
775*7c356e86SAndroid Build Coastguard Worker fptreef(shf, i, "%s %s %T", Tfunction, k, v);
776*7c356e86SAndroid Build Coastguard Worker else if (ktsearch(&keywords, k, hash(k)))
777*7c356e86SAndroid Build Coastguard Worker fptreef(shf, i, "%s %s() %T", Tfunction, k, v);
778*7c356e86SAndroid Build Coastguard Worker else
779*7c356e86SAndroid Build Coastguard Worker fptreef(shf, i, "%s() %T", k, v);
780*7c356e86SAndroid Build Coastguard Worker }
781*7c356e86SAndroid Build Coastguard Worker
782*7c356e86SAndroid Build Coastguard Worker
783*7c356e86SAndroid Build Coastguard Worker /* for jobs.c */
784*7c356e86SAndroid Build Coastguard Worker void
vistree(char * dst,size_t sz,struct op * t)785*7c356e86SAndroid Build Coastguard Worker vistree(char *dst, size_t sz, struct op *t)
786*7c356e86SAndroid Build Coastguard Worker {
787*7c356e86SAndroid Build Coastguard Worker unsigned int c;
788*7c356e86SAndroid Build Coastguard Worker char *cp, *buf;
789*7c356e86SAndroid Build Coastguard Worker size_t n;
790*7c356e86SAndroid Build Coastguard Worker
791*7c356e86SAndroid Build Coastguard Worker buf = alloc(sz + 16, ATEMP);
792*7c356e86SAndroid Build Coastguard Worker snptreef(buf, sz + 16, Tf_T, t);
793*7c356e86SAndroid Build Coastguard Worker cp = buf;
794*7c356e86SAndroid Build Coastguard Worker vist_loop:
795*7c356e86SAndroid Build Coastguard Worker if (UTFMODE && (n = utf_mbtowc(&c, cp)) != (size_t)-1) {
796*7c356e86SAndroid Build Coastguard Worker if (c == 0 || n >= sz)
797*7c356e86SAndroid Build Coastguard Worker /* NUL or not enough free space */
798*7c356e86SAndroid Build Coastguard Worker goto vist_out;
799*7c356e86SAndroid Build Coastguard Worker /* copy multibyte char */
800*7c356e86SAndroid Build Coastguard Worker sz -= n;
801*7c356e86SAndroid Build Coastguard Worker while (n--)
802*7c356e86SAndroid Build Coastguard Worker *dst++ = *cp++;
803*7c356e86SAndroid Build Coastguard Worker goto vist_loop;
804*7c356e86SAndroid Build Coastguard Worker }
805*7c356e86SAndroid Build Coastguard Worker if (--sz == 0 || (c = ord(*cp++)) == 0)
806*7c356e86SAndroid Build Coastguard Worker /* NUL or not enough free space */
807*7c356e86SAndroid Build Coastguard Worker goto vist_out;
808*7c356e86SAndroid Build Coastguard Worker if (ksh_isctrl(c)) {
809*7c356e86SAndroid Build Coastguard Worker /* C0 or C1 control character or DEL */
810*7c356e86SAndroid Build Coastguard Worker if (--sz == 0)
811*7c356e86SAndroid Build Coastguard Worker /* not enough free space for two chars */
812*7c356e86SAndroid Build Coastguard Worker goto vist_out;
813*7c356e86SAndroid Build Coastguard Worker *dst++ = '^';
814*7c356e86SAndroid Build Coastguard Worker c = ksh_unctrl(c);
815*7c356e86SAndroid Build Coastguard Worker } else if (UTFMODE && rtt2asc(c) > 0x7F) {
816*7c356e86SAndroid Build Coastguard Worker /* better not try to display broken multibyte chars */
817*7c356e86SAndroid Build Coastguard Worker /* also go easy on the UCS: no U+FFFD here */
818*7c356e86SAndroid Build Coastguard Worker c = ORD('?');
819*7c356e86SAndroid Build Coastguard Worker }
820*7c356e86SAndroid Build Coastguard Worker *dst++ = c;
821*7c356e86SAndroid Build Coastguard Worker goto vist_loop;
822*7c356e86SAndroid Build Coastguard Worker
823*7c356e86SAndroid Build Coastguard Worker vist_out:
824*7c356e86SAndroid Build Coastguard Worker *dst = '\0';
825*7c356e86SAndroid Build Coastguard Worker afree(buf, ATEMP);
826*7c356e86SAndroid Build Coastguard Worker }
827*7c356e86SAndroid Build Coastguard Worker
828*7c356e86SAndroid Build Coastguard Worker #ifdef DEBUG
829*7c356e86SAndroid Build Coastguard Worker void
dumpchar(struct shf * shf,unsigned char c)830*7c356e86SAndroid Build Coastguard Worker dumpchar(struct shf *shf, unsigned char c)
831*7c356e86SAndroid Build Coastguard Worker {
832*7c356e86SAndroid Build Coastguard Worker if (ksh_isctrl(c)) {
833*7c356e86SAndroid Build Coastguard Worker /* C0 or C1 control character or DEL */
834*7c356e86SAndroid Build Coastguard Worker shf_putc('^', shf);
835*7c356e86SAndroid Build Coastguard Worker c = ksh_unctrl(c);
836*7c356e86SAndroid Build Coastguard Worker }
837*7c356e86SAndroid Build Coastguard Worker shf_putc(c, shf);
838*7c356e86SAndroid Build Coastguard Worker }
839*7c356e86SAndroid Build Coastguard Worker
840*7c356e86SAndroid Build Coastguard Worker /* see: wdvarput */
841*7c356e86SAndroid Build Coastguard Worker static const char *
dumpwdvar_i(struct shf * shf,const char * wp,int quotelevel)842*7c356e86SAndroid Build Coastguard Worker dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
843*7c356e86SAndroid Build Coastguard Worker {
844*7c356e86SAndroid Build Coastguard Worker int c;
845*7c356e86SAndroid Build Coastguard Worker
846*7c356e86SAndroid Build Coastguard Worker while (/* CONSTCOND */ 1) {
847*7c356e86SAndroid Build Coastguard Worker switch(*wp++) {
848*7c356e86SAndroid Build Coastguard Worker case EOS:
849*7c356e86SAndroid Build Coastguard Worker shf_puts("EOS", shf);
850*7c356e86SAndroid Build Coastguard Worker return (--wp);
851*7c356e86SAndroid Build Coastguard Worker case ADELIM:
852*7c356e86SAndroid Build Coastguard Worker if (ord(*wp) == ORD(/*{*/ '}')) {
853*7c356e86SAndroid Build Coastguard Worker shf_puts(/*{*/ "]ADELIM(})", shf);
854*7c356e86SAndroid Build Coastguard Worker return (wp + 1);
855*7c356e86SAndroid Build Coastguard Worker }
856*7c356e86SAndroid Build Coastguard Worker shf_puts("ADELIM=", shf);
857*7c356e86SAndroid Build Coastguard Worker if (0)
858*7c356e86SAndroid Build Coastguard Worker /* FALLTHROUGH */
859*7c356e86SAndroid Build Coastguard Worker case CHAR:
860*7c356e86SAndroid Build Coastguard Worker shf_puts("CHAR=", shf);
861*7c356e86SAndroid Build Coastguard Worker dumpchar(shf, *wp++);
862*7c356e86SAndroid Build Coastguard Worker break;
863*7c356e86SAndroid Build Coastguard Worker case QCHAR:
864*7c356e86SAndroid Build Coastguard Worker shf_puts("QCHAR<", shf);
865*7c356e86SAndroid Build Coastguard Worker c = ord(*wp++);
866*7c356e86SAndroid Build Coastguard Worker if (quotelevel == 0 || c == ORD('"') ||
867*7c356e86SAndroid Build Coastguard Worker c == ORD('\\') || ctype(c, C_DOLAR | C_GRAVE))
868*7c356e86SAndroid Build Coastguard Worker shf_putc('\\', shf);
869*7c356e86SAndroid Build Coastguard Worker dumpchar(shf, c);
870*7c356e86SAndroid Build Coastguard Worker goto closeandout;
871*7c356e86SAndroid Build Coastguard Worker case COMASUB:
872*7c356e86SAndroid Build Coastguard Worker shf_puts("COMASUB<", shf);
873*7c356e86SAndroid Build Coastguard Worker goto dumpsub;
874*7c356e86SAndroid Build Coastguard Worker case COMSUB:
875*7c356e86SAndroid Build Coastguard Worker shf_puts("COMSUB<", shf);
876*7c356e86SAndroid Build Coastguard Worker dumpsub:
877*7c356e86SAndroid Build Coastguard Worker while ((c = *wp++) != 0)
878*7c356e86SAndroid Build Coastguard Worker dumpchar(shf, c);
879*7c356e86SAndroid Build Coastguard Worker closeandout:
880*7c356e86SAndroid Build Coastguard Worker shf_putc('>', shf);
881*7c356e86SAndroid Build Coastguard Worker break;
882*7c356e86SAndroid Build Coastguard Worker case FUNASUB:
883*7c356e86SAndroid Build Coastguard Worker shf_puts("FUNASUB<", shf);
884*7c356e86SAndroid Build Coastguard Worker goto dumpsub;
885*7c356e86SAndroid Build Coastguard Worker case FUNSUB:
886*7c356e86SAndroid Build Coastguard Worker shf_puts("FUNSUB<", shf);
887*7c356e86SAndroid Build Coastguard Worker goto dumpsub;
888*7c356e86SAndroid Build Coastguard Worker case VALSUB:
889*7c356e86SAndroid Build Coastguard Worker shf_puts("VALSUB<", shf);
890*7c356e86SAndroid Build Coastguard Worker goto dumpsub;
891*7c356e86SAndroid Build Coastguard Worker case EXPRSUB:
892*7c356e86SAndroid Build Coastguard Worker shf_puts("EXPRSUB<", shf);
893*7c356e86SAndroid Build Coastguard Worker goto dumpsub;
894*7c356e86SAndroid Build Coastguard Worker case OQUOTE:
895*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, "OQUOTE{%d" /*}*/, ++quotelevel);
896*7c356e86SAndroid Build Coastguard Worker break;
897*7c356e86SAndroid Build Coastguard Worker case CQUOTE:
898*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, /*{*/ "%d}CQUOTE", quotelevel);
899*7c356e86SAndroid Build Coastguard Worker if (quotelevel)
900*7c356e86SAndroid Build Coastguard Worker quotelevel--;
901*7c356e86SAndroid Build Coastguard Worker else
902*7c356e86SAndroid Build Coastguard Worker shf_puts("(err)", shf);
903*7c356e86SAndroid Build Coastguard Worker break;
904*7c356e86SAndroid Build Coastguard Worker case OSUBST:
905*7c356e86SAndroid Build Coastguard Worker shf_puts("OSUBST(", shf);
906*7c356e86SAndroid Build Coastguard Worker dumpchar(shf, *wp++);
907*7c356e86SAndroid Build Coastguard Worker shf_puts(")[", shf);
908*7c356e86SAndroid Build Coastguard Worker while ((c = *wp++) != 0)
909*7c356e86SAndroid Build Coastguard Worker dumpchar(shf, c);
910*7c356e86SAndroid Build Coastguard Worker shf_putc('|', shf);
911*7c356e86SAndroid Build Coastguard Worker wp = dumpwdvar_i(shf, wp, 0);
912*7c356e86SAndroid Build Coastguard Worker break;
913*7c356e86SAndroid Build Coastguard Worker case CSUBST:
914*7c356e86SAndroid Build Coastguard Worker shf_puts("]CSUBST(", shf);
915*7c356e86SAndroid Build Coastguard Worker dumpchar(shf, *wp++);
916*7c356e86SAndroid Build Coastguard Worker shf_putc(')', shf);
917*7c356e86SAndroid Build Coastguard Worker return (wp);
918*7c356e86SAndroid Build Coastguard Worker case OPAT:
919*7c356e86SAndroid Build Coastguard Worker shf_puts("OPAT=", shf);
920*7c356e86SAndroid Build Coastguard Worker dumpchar(shf, *wp++);
921*7c356e86SAndroid Build Coastguard Worker break;
922*7c356e86SAndroid Build Coastguard Worker case SPAT:
923*7c356e86SAndroid Build Coastguard Worker shf_puts("SPAT", shf);
924*7c356e86SAndroid Build Coastguard Worker break;
925*7c356e86SAndroid Build Coastguard Worker case CPAT:
926*7c356e86SAndroid Build Coastguard Worker shf_puts("CPAT", shf);
927*7c356e86SAndroid Build Coastguard Worker break;
928*7c356e86SAndroid Build Coastguard Worker default:
929*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, "INVAL<%u>", (uint8_t)wp[-1]);
930*7c356e86SAndroid Build Coastguard Worker break;
931*7c356e86SAndroid Build Coastguard Worker }
932*7c356e86SAndroid Build Coastguard Worker shf_putc(' ', shf);
933*7c356e86SAndroid Build Coastguard Worker }
934*7c356e86SAndroid Build Coastguard Worker }
935*7c356e86SAndroid Build Coastguard Worker void
dumpwdvar(struct shf * shf,const char * wp)936*7c356e86SAndroid Build Coastguard Worker dumpwdvar(struct shf *shf, const char *wp)
937*7c356e86SAndroid Build Coastguard Worker {
938*7c356e86SAndroid Build Coastguard Worker dumpwdvar_i(shf, wp, 0);
939*7c356e86SAndroid Build Coastguard Worker }
940*7c356e86SAndroid Build Coastguard Worker
941*7c356e86SAndroid Build Coastguard Worker void
dumpioact(struct shf * shf,struct op * t)942*7c356e86SAndroid Build Coastguard Worker dumpioact(struct shf *shf, struct op *t)
943*7c356e86SAndroid Build Coastguard Worker {
944*7c356e86SAndroid Build Coastguard Worker struct ioword **ioact, *iop;
945*7c356e86SAndroid Build Coastguard Worker
946*7c356e86SAndroid Build Coastguard Worker if ((ioact = t->ioact) == NULL)
947*7c356e86SAndroid Build Coastguard Worker return;
948*7c356e86SAndroid Build Coastguard Worker
949*7c356e86SAndroid Build Coastguard Worker shf_puts("{IOACT", shf);
950*7c356e86SAndroid Build Coastguard Worker while ((iop = *ioact++) != NULL) {
951*7c356e86SAndroid Build Coastguard Worker unsigned short type = iop->ioflag & IOTYPE;
952*7c356e86SAndroid Build Coastguard Worker #define DT(x) case x: shf_puts(#x, shf); break;
953*7c356e86SAndroid Build Coastguard Worker #define DB(x) if (iop->ioflag & x) shf_puts("|" #x, shf);
954*7c356e86SAndroid Build Coastguard Worker
955*7c356e86SAndroid Build Coastguard Worker shf_putc(';', shf);
956*7c356e86SAndroid Build Coastguard Worker switch (type) {
957*7c356e86SAndroid Build Coastguard Worker DT(IOREAD)
958*7c356e86SAndroid Build Coastguard Worker DT(IOWRITE)
959*7c356e86SAndroid Build Coastguard Worker DT(IORDWR)
960*7c356e86SAndroid Build Coastguard Worker DT(IOHERE)
961*7c356e86SAndroid Build Coastguard Worker DT(IOCAT)
962*7c356e86SAndroid Build Coastguard Worker DT(IODUP)
963*7c356e86SAndroid Build Coastguard Worker default:
964*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, "unk%d", type);
965*7c356e86SAndroid Build Coastguard Worker }
966*7c356e86SAndroid Build Coastguard Worker DB(IOEVAL)
967*7c356e86SAndroid Build Coastguard Worker DB(IOSKIP)
968*7c356e86SAndroid Build Coastguard Worker DB(IOCLOB)
969*7c356e86SAndroid Build Coastguard Worker DB(IORDUP)
970*7c356e86SAndroid Build Coastguard Worker DB(IONAMEXP)
971*7c356e86SAndroid Build Coastguard Worker DB(IOBASH)
972*7c356e86SAndroid Build Coastguard Worker DB(IOHERESTR)
973*7c356e86SAndroid Build Coastguard Worker DB(IONDELIM)
974*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, ",unit=%d", (int)iop->unit);
975*7c356e86SAndroid Build Coastguard Worker if (iop->delim && !(iop->ioflag & IONDELIM)) {
976*7c356e86SAndroid Build Coastguard Worker shf_puts(",delim<", shf);
977*7c356e86SAndroid Build Coastguard Worker dumpwdvar(shf, iop->delim);
978*7c356e86SAndroid Build Coastguard Worker shf_putc('>', shf);
979*7c356e86SAndroid Build Coastguard Worker }
980*7c356e86SAndroid Build Coastguard Worker if (iop->ioname) {
981*7c356e86SAndroid Build Coastguard Worker if (iop->ioflag & IONAMEXP) {
982*7c356e86SAndroid Build Coastguard Worker shf_puts(",name=", shf);
983*7c356e86SAndroid Build Coastguard Worker print_value_quoted(shf, iop->ioname);
984*7c356e86SAndroid Build Coastguard Worker } else {
985*7c356e86SAndroid Build Coastguard Worker shf_puts(",name<", shf);
986*7c356e86SAndroid Build Coastguard Worker dumpwdvar(shf, iop->ioname);
987*7c356e86SAndroid Build Coastguard Worker shf_putc('>', shf);
988*7c356e86SAndroid Build Coastguard Worker }
989*7c356e86SAndroid Build Coastguard Worker }
990*7c356e86SAndroid Build Coastguard Worker if (iop->heredoc) {
991*7c356e86SAndroid Build Coastguard Worker shf_puts(",heredoc=", shf);
992*7c356e86SAndroid Build Coastguard Worker print_value_quoted(shf, iop->heredoc);
993*7c356e86SAndroid Build Coastguard Worker }
994*7c356e86SAndroid Build Coastguard Worker #undef DT
995*7c356e86SAndroid Build Coastguard Worker #undef DB
996*7c356e86SAndroid Build Coastguard Worker }
997*7c356e86SAndroid Build Coastguard Worker shf_putc('}', shf);
998*7c356e86SAndroid Build Coastguard Worker }
999*7c356e86SAndroid Build Coastguard Worker
1000*7c356e86SAndroid Build Coastguard Worker void
dumptree(struct shf * shf,struct op * t)1001*7c356e86SAndroid Build Coastguard Worker dumptree(struct shf *shf, struct op *t)
1002*7c356e86SAndroid Build Coastguard Worker {
1003*7c356e86SAndroid Build Coastguard Worker int i, j;
1004*7c356e86SAndroid Build Coastguard Worker const char **w, *name;
1005*7c356e86SAndroid Build Coastguard Worker struct op *t1;
1006*7c356e86SAndroid Build Coastguard Worker static int nesting;
1007*7c356e86SAndroid Build Coastguard Worker
1008*7c356e86SAndroid Build Coastguard Worker for (i = 0; i < nesting; ++i)
1009*7c356e86SAndroid Build Coastguard Worker shf_putc('\t', shf);
1010*7c356e86SAndroid Build Coastguard Worker ++nesting;
1011*7c356e86SAndroid Build Coastguard Worker shf_puts("{tree:" /*}*/, shf);
1012*7c356e86SAndroid Build Coastguard Worker if (t == NULL) {
1013*7c356e86SAndroid Build Coastguard Worker name = "(null)";
1014*7c356e86SAndroid Build Coastguard Worker goto out;
1015*7c356e86SAndroid Build Coastguard Worker }
1016*7c356e86SAndroid Build Coastguard Worker dumpioact(shf, t);
1017*7c356e86SAndroid Build Coastguard Worker switch (t->type) {
1018*7c356e86SAndroid Build Coastguard Worker #define OPEN(x) case x: name = #x; shf_puts(" {" #x ":", shf); /*}*/
1019*7c356e86SAndroid Build Coastguard Worker
1020*7c356e86SAndroid Build Coastguard Worker OPEN(TCOM)
1021*7c356e86SAndroid Build Coastguard Worker if (t->vars) {
1022*7c356e86SAndroid Build Coastguard Worker i = 0;
1023*7c356e86SAndroid Build Coastguard Worker w = (const char **)t->vars;
1024*7c356e86SAndroid Build Coastguard Worker while (*w) {
1025*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', shf);
1026*7c356e86SAndroid Build Coastguard Worker for (j = 0; j < nesting; ++j)
1027*7c356e86SAndroid Build Coastguard Worker shf_putc('\t', shf);
1028*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, " var%d<", i++);
1029*7c356e86SAndroid Build Coastguard Worker dumpwdvar(shf, *w++);
1030*7c356e86SAndroid Build Coastguard Worker shf_putc('>', shf);
1031*7c356e86SAndroid Build Coastguard Worker }
1032*7c356e86SAndroid Build Coastguard Worker } else
1033*7c356e86SAndroid Build Coastguard Worker shf_puts(" #no-vars#", shf);
1034*7c356e86SAndroid Build Coastguard Worker if (t->args) {
1035*7c356e86SAndroid Build Coastguard Worker i = 0;
1036*7c356e86SAndroid Build Coastguard Worker w = t->args;
1037*7c356e86SAndroid Build Coastguard Worker while (*w) {
1038*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', shf);
1039*7c356e86SAndroid Build Coastguard Worker for (j = 0; j < nesting; ++j)
1040*7c356e86SAndroid Build Coastguard Worker shf_putc('\t', shf);
1041*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, " arg%d<", i++);
1042*7c356e86SAndroid Build Coastguard Worker dumpwdvar(shf, *w++);
1043*7c356e86SAndroid Build Coastguard Worker shf_putc('>', shf);
1044*7c356e86SAndroid Build Coastguard Worker }
1045*7c356e86SAndroid Build Coastguard Worker } else
1046*7c356e86SAndroid Build Coastguard Worker shf_puts(" #no-args#", shf);
1047*7c356e86SAndroid Build Coastguard Worker break;
1048*7c356e86SAndroid Build Coastguard Worker OPEN(TEXEC)
1049*7c356e86SAndroid Build Coastguard Worker dumpleftandout:
1050*7c356e86SAndroid Build Coastguard Worker t = t->left;
1051*7c356e86SAndroid Build Coastguard Worker dumpandout:
1052*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', shf);
1053*7c356e86SAndroid Build Coastguard Worker dumptree(shf, t);
1054*7c356e86SAndroid Build Coastguard Worker break;
1055*7c356e86SAndroid Build Coastguard Worker OPEN(TPAREN)
1056*7c356e86SAndroid Build Coastguard Worker goto dumpleftandout;
1057*7c356e86SAndroid Build Coastguard Worker OPEN(TPIPE)
1058*7c356e86SAndroid Build Coastguard Worker dumpleftmidrightandout:
1059*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', shf);
1060*7c356e86SAndroid Build Coastguard Worker dumptree(shf, t->left);
1061*7c356e86SAndroid Build Coastguard Worker /* middumprightandout: (unused) */
1062*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, "/%s:", name);
1063*7c356e86SAndroid Build Coastguard Worker dumprightandout:
1064*7c356e86SAndroid Build Coastguard Worker t = t->right;
1065*7c356e86SAndroid Build Coastguard Worker goto dumpandout;
1066*7c356e86SAndroid Build Coastguard Worker OPEN(TLIST)
1067*7c356e86SAndroid Build Coastguard Worker goto dumpleftmidrightandout;
1068*7c356e86SAndroid Build Coastguard Worker OPEN(TOR)
1069*7c356e86SAndroid Build Coastguard Worker goto dumpleftmidrightandout;
1070*7c356e86SAndroid Build Coastguard Worker OPEN(TAND)
1071*7c356e86SAndroid Build Coastguard Worker goto dumpleftmidrightandout;
1072*7c356e86SAndroid Build Coastguard Worker OPEN(TBANG)
1073*7c356e86SAndroid Build Coastguard Worker goto dumprightandout;
1074*7c356e86SAndroid Build Coastguard Worker OPEN(TDBRACKET)
1075*7c356e86SAndroid Build Coastguard Worker i = 0;
1076*7c356e86SAndroid Build Coastguard Worker w = t->args;
1077*7c356e86SAndroid Build Coastguard Worker while (*w) {
1078*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', shf);
1079*7c356e86SAndroid Build Coastguard Worker for (j = 0; j < nesting; ++j)
1080*7c356e86SAndroid Build Coastguard Worker shf_putc('\t', shf);
1081*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, " arg%d<", i++);
1082*7c356e86SAndroid Build Coastguard Worker dumpwdvar(shf, *w++);
1083*7c356e86SAndroid Build Coastguard Worker shf_putc('>', shf);
1084*7c356e86SAndroid Build Coastguard Worker }
1085*7c356e86SAndroid Build Coastguard Worker break;
1086*7c356e86SAndroid Build Coastguard Worker OPEN(TFOR)
1087*7c356e86SAndroid Build Coastguard Worker dumpfor:
1088*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, " str<%s>", t->str);
1089*7c356e86SAndroid Build Coastguard Worker if (t->vars != NULL) {
1090*7c356e86SAndroid Build Coastguard Worker i = 0;
1091*7c356e86SAndroid Build Coastguard Worker w = (const char **)t->vars;
1092*7c356e86SAndroid Build Coastguard Worker while (*w) {
1093*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', shf);
1094*7c356e86SAndroid Build Coastguard Worker for (j = 0; j < nesting; ++j)
1095*7c356e86SAndroid Build Coastguard Worker shf_putc('\t', shf);
1096*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, " var%d<", i++);
1097*7c356e86SAndroid Build Coastguard Worker dumpwdvar(shf, *w++);
1098*7c356e86SAndroid Build Coastguard Worker shf_putc('>', shf);
1099*7c356e86SAndroid Build Coastguard Worker }
1100*7c356e86SAndroid Build Coastguard Worker }
1101*7c356e86SAndroid Build Coastguard Worker goto dumpleftandout;
1102*7c356e86SAndroid Build Coastguard Worker OPEN(TSELECT)
1103*7c356e86SAndroid Build Coastguard Worker goto dumpfor;
1104*7c356e86SAndroid Build Coastguard Worker OPEN(TCASE)
1105*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, " str<%s>", t->str);
1106*7c356e86SAndroid Build Coastguard Worker i = 0;
1107*7c356e86SAndroid Build Coastguard Worker for (t1 = t->left; t1 != NULL; t1 = t1->right) {
1108*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', shf);
1109*7c356e86SAndroid Build Coastguard Worker for (j = 0; j < nesting; ++j)
1110*7c356e86SAndroid Build Coastguard Worker shf_putc('\t', shf);
1111*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, " sub%d[(", i);
1112*7c356e86SAndroid Build Coastguard Worker w = (const char **)t1->vars;
1113*7c356e86SAndroid Build Coastguard Worker while (*w) {
1114*7c356e86SAndroid Build Coastguard Worker dumpwdvar(shf, *w);
1115*7c356e86SAndroid Build Coastguard Worker if (w[1] != NULL)
1116*7c356e86SAndroid Build Coastguard Worker shf_putc('|', shf);
1117*7c356e86SAndroid Build Coastguard Worker ++w;
1118*7c356e86SAndroid Build Coastguard Worker }
1119*7c356e86SAndroid Build Coastguard Worker shf_putc(')', shf);
1120*7c356e86SAndroid Build Coastguard Worker dumpioact(shf, t);
1121*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', shf);
1122*7c356e86SAndroid Build Coastguard Worker dumptree(shf, t1->left);
1123*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, " ;%c/%d]", t1->u.charflag, i++);
1124*7c356e86SAndroid Build Coastguard Worker }
1125*7c356e86SAndroid Build Coastguard Worker break;
1126*7c356e86SAndroid Build Coastguard Worker OPEN(TWHILE)
1127*7c356e86SAndroid Build Coastguard Worker goto dumpleftmidrightandout;
1128*7c356e86SAndroid Build Coastguard Worker OPEN(TUNTIL)
1129*7c356e86SAndroid Build Coastguard Worker goto dumpleftmidrightandout;
1130*7c356e86SAndroid Build Coastguard Worker OPEN(TBRACE)
1131*7c356e86SAndroid Build Coastguard Worker goto dumpleftandout;
1132*7c356e86SAndroid Build Coastguard Worker OPEN(TCOPROC)
1133*7c356e86SAndroid Build Coastguard Worker goto dumpleftandout;
1134*7c356e86SAndroid Build Coastguard Worker OPEN(TASYNC)
1135*7c356e86SAndroid Build Coastguard Worker goto dumpleftandout;
1136*7c356e86SAndroid Build Coastguard Worker OPEN(TFUNCT)
1137*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, " str<%s> ksh<%s>", t->str,
1138*7c356e86SAndroid Build Coastguard Worker t->u.ksh_func ? Ttrue : Tfalse);
1139*7c356e86SAndroid Build Coastguard Worker goto dumpleftandout;
1140*7c356e86SAndroid Build Coastguard Worker OPEN(TTIME)
1141*7c356e86SAndroid Build Coastguard Worker goto dumpleftandout;
1142*7c356e86SAndroid Build Coastguard Worker OPEN(TIF)
1143*7c356e86SAndroid Build Coastguard Worker dumpif:
1144*7c356e86SAndroid Build Coastguard Worker shf_putc('\n', shf);
1145*7c356e86SAndroid Build Coastguard Worker dumptree(shf, t->left);
1146*7c356e86SAndroid Build Coastguard Worker t = t->right;
1147*7c356e86SAndroid Build Coastguard Worker dumpioact(shf, t);
1148*7c356e86SAndroid Build Coastguard Worker if (t->left != NULL) {
1149*7c356e86SAndroid Build Coastguard Worker shf_puts(" /TTHEN:\n", shf);
1150*7c356e86SAndroid Build Coastguard Worker dumptree(shf, t->left);
1151*7c356e86SAndroid Build Coastguard Worker }
1152*7c356e86SAndroid Build Coastguard Worker if (t->right && t->right->type == TELIF) {
1153*7c356e86SAndroid Build Coastguard Worker shf_puts(" /TELIF:", shf);
1154*7c356e86SAndroid Build Coastguard Worker t = t->right;
1155*7c356e86SAndroid Build Coastguard Worker dumpioact(shf, t);
1156*7c356e86SAndroid Build Coastguard Worker goto dumpif;
1157*7c356e86SAndroid Build Coastguard Worker }
1158*7c356e86SAndroid Build Coastguard Worker if (t->right != NULL) {
1159*7c356e86SAndroid Build Coastguard Worker shf_puts(" /TELSE:\n", shf);
1160*7c356e86SAndroid Build Coastguard Worker dumptree(shf, t->right);
1161*7c356e86SAndroid Build Coastguard Worker }
1162*7c356e86SAndroid Build Coastguard Worker break;
1163*7c356e86SAndroid Build Coastguard Worker OPEN(TEOF)
1164*7c356e86SAndroid Build Coastguard Worker dumpunexpected:
1165*7c356e86SAndroid Build Coastguard Worker shf_puts(Tunexpected, shf);
1166*7c356e86SAndroid Build Coastguard Worker break;
1167*7c356e86SAndroid Build Coastguard Worker OPEN(TELIF)
1168*7c356e86SAndroid Build Coastguard Worker goto dumpunexpected;
1169*7c356e86SAndroid Build Coastguard Worker OPEN(TPAT)
1170*7c356e86SAndroid Build Coastguard Worker goto dumpunexpected;
1171*7c356e86SAndroid Build Coastguard Worker default:
1172*7c356e86SAndroid Build Coastguard Worker name = "TINVALID";
1173*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, "{T<%d>:" /*}*/, t->type);
1174*7c356e86SAndroid Build Coastguard Worker goto dumpunexpected;
1175*7c356e86SAndroid Build Coastguard Worker
1176*7c356e86SAndroid Build Coastguard Worker #undef OPEN
1177*7c356e86SAndroid Build Coastguard Worker }
1178*7c356e86SAndroid Build Coastguard Worker out:
1179*7c356e86SAndroid Build Coastguard Worker shf_fprintf(shf, /*{*/ " /%s}\n", name);
1180*7c356e86SAndroid Build Coastguard Worker --nesting;
1181*7c356e86SAndroid Build Coastguard Worker }
1182*7c356e86SAndroid Build Coastguard Worker #endif
1183