1fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes/*	$OpenBSD: tree.c,v 1.21 2015/09/01 13:12:31 tedu Exp $	*/
25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*-
4c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
5a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes *		 2011, 2012, 2013, 2015, 2016, 2017
6fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes *	mirabilos <m@mirbsd.org>
75155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
85155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices
95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission
105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un-
115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify,
125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence.
135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor
165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event
175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect,
185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out
195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such
205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out
215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended.
225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h"
255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.89 2017/04/12 16:46:23 tg Exp $");
275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define INDENT	8
295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void ptree(struct op *, int, struct shf *);
31811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstatic void pioact(struct shf *, struct ioword *);
3203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const char *wdvarput(struct shf *, const char *, int, int);
335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void vfptreef(struct shf *, int, const char *, va_list);
345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct ioword **iocopy(struct ioword **, Area *);
355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void iofree(struct ioword **, Area *);
365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* "foo& ; bar" and "foo |& ; bar" are invalid */
3803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic bool prevent_semicolon;
3903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
40c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const char Telif_pT[] = "elif %T";
41c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * print a command tree
445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruptree(struct op *t, int indent, struct shf *shf)
475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char **w;
495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct ioword **ioact;
505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct op *t1;
5103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int i;
5277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	const char *ccp;
535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Chain:
555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t == NULL)
565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch (t->type) {
585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TCOM:
59c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		prevent_semicolon = false;
6077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		/* special-case 'var=<<EOF' (cf. exec.c:execute) */
61a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		if (t->args &&
6277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		    /* we have zero arguments, i.e. no program to run */
63c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    t->args[0] == NULL &&
64c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    /* we have exactly one variable assignment */
65c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    t->vars[0] != NULL && t->vars[1] == NULL &&
66c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    /* we have exactly one I/O redirection */
67c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    t->ioact != NULL && t->ioact[0] != NULL &&
68c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    t->ioact[1] == NULL &&
69c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    /* of type "here document" (or "here string") */
7077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		    (t->ioact[0]->ioflag & IOTYPE) == IOHERE &&
7177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		    /* the variable assignment begins with a valid varname */
7277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		    (ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] &&
7377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		    /* and has no right-hand side (i.e. "varname=") */
7477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		    ccp[0] == CHAR && ((ccp[1] == '=' && ccp[2] == EOS) ||
7577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		    /* or "varname+=" */ (ccp[1] == '+' && ccp[2] == CHAR &&
7677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		    ccp[3] == '=' && ccp[4] == EOS))) {
7777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			fptreef(shf, indent, Tf_S, t->vars[0]);
78c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			break;
79c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
80c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
8103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->vars) {
8203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = (const char **)t->vars;
8303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w)
8477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				fptreef(shf, indent, Tf_S_, *w++);
8503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts("#no-vars# ", shf);
8703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->args) {
8803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = t->args;
89a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			if (*w && **w == CHAR) {
90a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes				char *cp = wdstrip(*w++, WDS_TPUTS);
91a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes
92a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes				if (valid_alias_name(cp))
93a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes					shf_putc('\\', shf);
94a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes				shf_puts(cp, shf);
95a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes				shf_putc(' ', shf);
96a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes				afree(cp, ATEMP);
97a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			}
9803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w)
9977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				fptreef(shf, indent, Tf_S_, *w++);
10003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts("#no-args# ", shf);
1025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TEXEC:
1045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		t = t->left;
1055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto Chain;
1065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TPAREN:
1075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent + 2, "( %T) ", t->left);
1085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TPIPE:
1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%T| ", t->left);
1115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		t = t->right;
1125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto Chain;
1135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TLIST:
1145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%T%;", t->left);
1155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		t = t->right;
1165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto Chain;
1175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TOR:
1185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TAND:
1195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%T%s %T",
12003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    t->left, (t->type == TOR) ? "||" : "&&", t->right);
1215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TBANG:
1235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts("! ", shf);
12403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		prevent_semicolon = false;
1255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		t = t->right;
1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto Chain;
12703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TDBRACKET:
12803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		w = t->args;
1295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts("[[", shf);
13003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*w)
13177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			fptreef(shf, indent, Tf__S, *w++);
1325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts(" ]] ", shf);
1335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TSELECT:
1355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TFOR:
13603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fptreef(shf, indent, "%s %s ",
13703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    (t->type == TFOR) ? "for" : Tselect, t->str);
1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (t->vars != NULL) {
1395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts("in ", shf);
14003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = (const char **)t->vars;
14103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w)
14277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				fptreef(shf, indent, Tf_S_, *w++);
14377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			fptreef(shf, indent, Tft_end);
1445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent + INDENT, "do%N%T", t->left);
1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%;done ");
1475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TCASE:
1495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "case %S in", t->str);
1505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (t1 = t->left; t1 != NULL; t1 = t1->right) {
1515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fptreef(shf, indent, "%N(");
15203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = (const char **)t1->vars;
15303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w) {
1545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				fptreef(shf, indent, "%S%c", *w,
1555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    (w[1] != NULL) ? '|' : ')');
15603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				++w;
15703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
15803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			fptreef(shf, indent + INDENT, "%N%T%N;%c", t1->left,
15903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    t1->u.charflag);
1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%Nesac ");
1625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TELIF:
16477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		internal_errorf(TELIF_unexpected);
16503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* FALLTHROUGH */
16603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TIF:
16703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		i = 2;
168c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		t1 = t;
16903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto process_TIF;
17003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		do {
171c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			t1 = t1->right;
17203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			i = 0;
17377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			fptreef(shf, indent, Tft_end);
17403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra process_TIF:
17503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* 5 == strlen("elif ") */
176c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			fptreef(shf, indent + 5 - i, Telif_pT + i, t1->left);
177c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			t1 = t1->right;
178c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if (t1->left != NULL) {
17977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				fptreef(shf, indent, Tft_end);
18003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				fptreef(shf, indent + INDENT, "%s%N%T",
181c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				    "then", t1->left);
1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
183c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		} while (t1->right && t1->right->type == TELIF);
184c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (t1->right != NULL) {
18577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			fptreef(shf, indent, Tft_end);
18603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			fptreef(shf, indent + INDENT, "%s%N%T",
187c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			    "else", t1->right);
1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%;fi ");
1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TWHILE:
1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TUNTIL:
193c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* 6 == strlen("while "/"until ") */
19477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		fptreef(shf, indent + 6, Tf_s_T,
19503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    (t->type == TWHILE) ? "while" : "until",
1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    t->left);
19777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		fptreef(shf, indent, Tft_end);
19803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fptreef(shf, indent + INDENT, "do%N%T", t->right);
1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%;done ");
2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TBRACE:
20203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fptreef(shf, indent + INDENT, "{%N%T", t->left);
2035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%;} ");
2045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TCOPROC:
2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%T|& ", t->left);
20703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		prevent_semicolon = true;
2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TASYNC:
2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%T& ", t->left);
21103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		prevent_semicolon = true;
2125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TFUNCT:
21403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fpFUNCTf(shf, indent, tobool(t->u.ksh_func), t->str, t->left);
2155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TTIME:
21777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		fptreef(shf, indent, Tf_s_T, Ttime, t->left);
2185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	default:
2205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts("<botch>", shf);
22103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		prevent_semicolon = false;
2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((ioact = t->ioact) != NULL) {
22503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bool need_nl = false;
2265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (*ioact != NULL)
228811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			pioact(shf, *ioact++);
2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* Print here documents after everything else... */
23003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		ioact = t->ioact;
23103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*ioact != NULL) {
2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			struct ioword *iop = *ioact++;
2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* heredoc is NULL when tracing (set -x) */
235b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes			if ((iop->ioflag & (IOTYPE | IOHERESTR)) == IOHERE &&
23603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    iop->heredoc) {
23703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\n', shf);
2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_puts(iop->heredoc, shf);
23977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				fptreef(shf, indent, Tf_s,
2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    evalstr(iop->delim, 0));
24103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				need_nl = true;
2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
24403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
24503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Last delimiter must be followed by a newline (this
24603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * often leads to an extra blank line, but it's not
24703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * worth worrying about)
2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
249c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (need_nl) {
25003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('\n', shf);
251c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			prevent_semicolon = true;
252c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
257811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserpioact(struct shf *shf, struct ioword *iop)
2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
259b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes	unsigned short flag = iop->ioflag;
260b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes	unsigned short type = flag & IOTYPE;
261b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes	short expected;
2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 :
2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (type == IOCAT || type == IOWRITE) ? 1 :
2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit :
2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    iop->unit + 1;
2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (iop->unit != expected)
26877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		shf_fprintf(shf, Tf_d, (int)iop->unit);
2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch (type) {
2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case IOREAD:
272811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		shf_putc('<', shf);
2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case IOHERE:
275811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		shf_puts("<<", shf);
276811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		if (flag & IOSKIP)
277811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			shf_putc('-', shf);
278fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes		else if (flag & IOHERESTR)
279fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			shf_putc('<', shf);
2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case IOCAT:
28203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_puts(">>", shf);
2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case IOWRITE:
285811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		shf_putc('>', shf);
286811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		if (flag & IOCLOB)
287811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			shf_putc('|', shf);
2885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case IORDWR:
29003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_puts("<>", shf);
2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case IODUP:
2935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts(flag & IORDUP ? "<&" : ">&", shf);
2945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
29603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* name/delim are NULL when printing syntax errors */
2975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (type == IOHERE) {
298fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes		if (iop->delim && !(iop->ioflag & IONDELIM))
299c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			wdvarput(shf, iop->delim, 0, WDS_TPUTS);
300fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes	} else if (iop->ioname) {
301b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes		if (flag & IONAMEXP)
302fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			print_value_quoted(shf, iop->ioname);
303811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		else
304fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			wdvarput(shf, iop->ioname, 0, WDS_TPUTS);
305811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	}
306fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes	shf_putc(' ', shf);
30703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	prevent_semicolon = false;
3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* variant of fputs for ptreef and wdstrip */
31103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const char *
31203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrawdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
3135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
31403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int c;
315c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	const char *cs;
3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*-
31803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * problems:
3195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	`...` -> $(...)
3205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	'foo' -> "foo"
32103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 *	x${foo:-"hi"} -> x${foo:-hi} unless WDS_TPUTS
322fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes	 *	x${foo:-'hi'} -> x${foo:-hi}
3235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * could change encoding to:
3245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	OQUOTE ["'] ... CQUOTE ["']
3255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	COMSUB [(`] ...\0	(handle $ ` \ and maybe " in `...` case)
3265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
32703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (/* CONSTCOND */ 1)
3285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (*wp++) {
3295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case EOS:
33003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (--wp);
3315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case ADELIM:
332fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			if (*wp == /*{*/'}') {
333fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes				++wp;
334fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes				goto wdvarput_csubst;
335fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			}
33677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			/* FALLTHROUGH */
3375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CHAR:
33803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			c = *wp++;
33903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(c, shf);
3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
34177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		case QCHAR:
3425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			c = *wp++;
34377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			if (opmode & WDS_TPUTS)
34477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				switch (c) {
34577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				case '\n':
34677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes					if (quotelevel == 0) {
34777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes						c = '\'';
34877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes						shf_putc(c, shf);
34977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes						shf_putc('\n', shf);
35077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes					}
35177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes					break;
35277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				default:
35377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes					if (quotelevel == 0)
35477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes						/* FALLTHROUGH */
35577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				case '"':
35677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				case '`':
35777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				case '$':
35877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				case '\\':
35977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes					  shf_putc('\\', shf);
36077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes					break;
36177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				}
36203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(c, shf);
3635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
364a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		case COMASUB:
3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case COMSUB:
3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts("$(", shf);
367c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			cs = ")";
368a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			if (*wp == '(' /*)*/)
369a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes				shf_putc(' ', shf);
370c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser pSUB:
37103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while ((c = *wp++) != 0)
37203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc(c, shf);
373c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			shf_puts(cs, shf);
3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
375a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		case FUNASUB:
376c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		case FUNSUB:
377811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			c = ' ';
378811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			if (0)
379811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser				/* FALLTHROUGH */
380811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		case VALSUB:
381811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			  c = '|';
382811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			shf_putc('$', shf);
383811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			shf_putc('{', shf);
384811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			shf_putc(c, shf);
385c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			cs = ";}";
386c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			goto pSUB;
3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case EXPRSUB:
3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts("$((", shf);
389c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			cs = "))";
390c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			goto pSUB;
3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case OQUOTE:
39203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (opmode & WDS_TPUTS) {
39303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				quotelevel++;
39403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('"', shf);
39503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CQUOTE:
39803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (opmode & WDS_TPUTS) {
39903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (quotelevel)
40003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					quotelevel--;
40103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('"', shf);
40203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
4045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case OSUBST:
40503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('$', shf);
4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*wp++ == '{')
40703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('{', shf);
4085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while ((c = *wp++) != 0)
40903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc(c, shf);
41003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			wp = wdvarput(shf, wp, 0, opmode);
4115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
4125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CSUBST:
413fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			if (*wp++ == '}') {
414fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes wdvarput_csubst:
41503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('}', shf);
416fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			}
41703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (wp);
4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case OPAT:
419fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			shf_putchar(*wp++, shf);
420fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			shf_putc('(', shf);
4215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
4225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SPAT:
42303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			c = '|';
42403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (0)
425a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes				/* FALLTHROUGH */
4265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CPAT:
427a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			  c = /*(*/ ')';
42803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(c, shf);
4295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
4305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
4315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * this is the _only_ way to reliably handle
4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * variable args with an ANSI compiler
4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* VARARGS */
43803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
4395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querufptreef(struct shf *shf, int indent, const char *fmt, ...)
4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
4425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_start(va, fmt);
4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vfptreef(shf, indent, fmt, va);
4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_end(va);
4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* VARARGS */
4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar *
45003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrasnptreef(char *s, ssize_t n, const char *fmt, ...)
4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct shf shf;
4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_sopen(s, n, SHF_WR | (s ? 0 : SHF_DYNAMIC), &shf);
4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_start(va, fmt);
4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vfptreef(&shf, 0, fmt, va);
4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_end(va);
4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
46103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* shf_sclose NUL terminates */
46203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (shf_sclose(&shf));
4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
4665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int c;
4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((c = *fmt++)) {
4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '%') {
4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			switch ((c = *fmt++)) {
4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'c':
47403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* character (octet, probably) */
47503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putchar(va_arg(va, int), shf);
4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 's':
47803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* string */
4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_puts(va_arg(va, char *), shf);
4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
48103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case 'S':
48203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* word */
48303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				wdvarput(shf, va_arg(va, char *), 0, WDS_TPUTS);
4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
48503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case 'd':
48603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* signed decimal */
48777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				shf_fprintf(shf, Tf_d, va_arg(va, int));
4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
48903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case 'u':
49003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* unsigned decimal */
4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_fprintf(shf, "%u", va_arg(va, unsigned int));
4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
49303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case 'T':
49403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* format tree */
4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ptree(va_arg(va, struct op *), indent, shf);
49603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				goto dont_trash_prevent_semicolon;
49703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case ';':
49803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* newline or ; */
49903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case 'N':
50003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* newline or space */
5015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (shf->flags & SHF_STRING) {
50203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					if (c == ';' && !prevent_semicolon)
50303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						shf_putc(';', shf);
50403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc(' ', shf);
5055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else {
5065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					int i;
5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
50803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc('\n', shf);
50903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					i = indent;
51003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					while (i >= 8) {
51103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						shf_putc('\t', shf);
51203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						i -= 8;
51303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					}
51403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					while (i--)
51503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						shf_putc(' ', shf);
5165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
5175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
5185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'R':
51903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* I/O redirection */
520811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser				pioact(shf, va_arg(va, struct ioword *));
5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
5225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			default:
52303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc(c, shf);
5245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
5265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
52703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(c, shf);
52803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		prevent_semicolon = false;
52903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dont_trash_prevent_semicolon:
53003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		;
5315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
5355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * copy tree (for function definition)
5365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
5375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct op *
5385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutcopy(struct op *t, Area *ap)
5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
5405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct op *r;
5415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char **tw;
5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char **rw;
5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t == NULL)
5455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (NULL);
5465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r = alloc(sizeof(struct op), ap);
5485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r->type = t->type;
5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r->u.evalflags = t->u.evalflags;
5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->type == TCASE)
5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		r->str = wdcopy(t->str, ap);
5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strdupx(r->str, t->str, ap);
5565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->vars == NULL)
5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		r->vars = NULL;
5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else {
56003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		tw = (const char **)t->vars;
56103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*tw)
56203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			++tw;
56303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		rw = r->vars = alloc2(tw - (const char **)t->vars + 1,
5645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    sizeof(*tw), ap);
56503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		tw = (const char **)t->vars;
56603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*tw)
5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*rw++ = wdcopy(*tw++, ap);
5685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*rw = NULL;
5695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->args == NULL)
5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		r->args = NULL;
5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else {
57403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		tw = t->args;
57503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*tw)
57603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			++tw;
57703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		r->args = (const char **)(rw = alloc2(tw - t->args + 1,
5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    sizeof(*tw), ap));
57903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		tw = t->args;
58003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*tw)
5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*rw++ = wdcopy(*tw++, ap);
5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*rw = NULL;
5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap);
5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r->left = tcopy(t->left, ap);
5885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r->right = tcopy(t->right, ap);
5895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r->lineno = t->lineno;
5905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (r);
5925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
5935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar *
5955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruwdcopy(const char *wp, Area *ap)
5965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
59703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t len;
59803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
59903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	len = wdscan(wp, EOS) - wp;
6005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (memcpy(alloc(len, ap), wp, len));
6015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* return the position of prefix c in wp plus 1 */
6045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruconst char *
6055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruwdscan(const char *wp, int c)
6065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int nest = 0;
6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
60903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (/* CONSTCOND */ 1)
6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (*wp++) {
6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case EOS:
6125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (wp);
6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case ADELIM:
614fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			if (c == ADELIM && nest == 0)
6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (wp + 1);
616fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			if (*wp == /*{*/'}')
617fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes				goto wdscan_csubst;
6185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* FALLTHROUGH */
6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CHAR:
6205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case QCHAR:
6215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			wp++;
6225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
623a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		case COMASUB:
6245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case COMSUB:
625a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		case FUNASUB:
626c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		case FUNSUB:
627811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		case VALSUB:
6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case EXPRSUB:
6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (*wp++ != 0)
6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				;
6315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case OQUOTE:
6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CQUOTE:
6345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case OSUBST:
6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nest++;
6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (*wp++ != '\0')
6385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				;
6395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CSUBST:
641fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes wdscan_csubst:
6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			wp++;
6435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == CSUBST && nest == 0)
6445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (wp);
6455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nest--;
6465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case OPAT:
6485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nest++;
6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			wp++;
6505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SPAT:
6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CPAT:
6535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == wp[-1] && nest == 0)
6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (wp);
6555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (wp[-1] == CPAT)
6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				nest--;
6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		default:
6595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			internal_warningf(
66077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			    "wdscan: unknown char 0x%X (carrying on)",
66177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			    (unsigned char)wp[-1]);
6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
6635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
66503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
66603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * return a copy of wp without any of the mark up characters and with
66703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * quote characters (" ' \) stripped. (string is allocated from ATEMP)
6685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
6695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar *
67003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrawdstrip(const char *wp, int opmode)
6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct shf shf;
6735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_sopen(NULL, 32, SHF_WR | SHF_DYNAMIC, &shf);
67503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	wdvarput(&shf, wp, 0, opmode);
67603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* shf_sclose NUL terminates */
67703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (shf_sclose(&shf));
6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct ioword **
6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruiocopy(struct ioword **iow, Area *ap)
6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct ioword **ior;
6845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
6855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
68603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ior = iow;
68703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (*ior)
68803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++ior;
68903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ior = alloc2(ior - iow + 1, sizeof(struct ioword *), ap);
6905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (i = 0; iow[i] != NULL; i++) {
6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct ioword *p, *q;
6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p = iow[i];
6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		q = alloc(sizeof(struct ioword), ap);
6965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ior[i] = q;
6975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*q = *p;
698fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes		if (p->ioname != NULL)
699fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			q->ioname = wdcopy(p->ioname, ap);
7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->delim != NULL)
7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			q->delim = wdcopy(p->delim, ap);
7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->heredoc != NULL)
7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			strdupx(q->heredoc, p->heredoc, ap);
7045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ior[i] = NULL;
7065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (ior);
7085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * free tree (for function definition)
7125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
7135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutfree(struct op *t, Area *ap)
7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char **w;
7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t == NULL)
7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
7205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
721fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes	afree(t->str, ap);
7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->vars != NULL) {
7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (w = t->vars; *w != NULL; w++)
7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(*w, ap);
7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(t->vars, ap);
7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->args != NULL) {
73003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*XXX we assume the caller is right */
7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		union mksh_ccphack cw;
73203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
7335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		cw.ro = t->args;
7345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (w = cw.rw; *w != NULL; w++)
7355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(*w, ap);
7365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(t->args, ap);
7375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->ioact != NULL)
7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		iofree(t->ioact, ap);
7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tfree(t->left, ap);
7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tfree(t->right, ap);
7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(t, ap);
7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
7475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruiofree(struct ioword **iow, Area *ap)
7505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
7515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct ioword **iop;
7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct ioword *p;
7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
75403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	iop = iow;
75503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while ((p = *iop++) != NULL) {
756fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes		afree(p->ioname, ap);
757fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes		afree(p->delim, ap);
758fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes		afree(p->heredoc, ap);
7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(p, ap);
7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(iow, ap);
7625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
76303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
76403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
76503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy CondrafpFUNCTf(struct shf *shf, int i, bool isksh, const char *k, struct op *v)
76603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
76703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (isksh)
76803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fptreef(shf, i, "%s %s %T", Tfunction, k, v);
769fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes	else if (ktsearch(&keywords, k, hash(k)))
770fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes		fptreef(shf, i, "%s %s() %T", Tfunction, k, v);
77103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else
77203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fptreef(shf, i, "%s() %T", k, v);
77303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
77403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
77503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
77603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* for jobs.c */
77703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
77803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravistree(char *dst, size_t sz, struct op *t)
77903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
780c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	unsigned int c;
78103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char *cp, *buf;
782c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	size_t n;
78303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
784811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	buf = alloc(sz + 16, ATEMP);
78577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	snptreef(buf, sz + 16, Tf_T, t);
78603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	cp = buf;
787c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser vist_loop:
788c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (UTFMODE && (n = utf_mbtowc(&c, cp)) != (size_t)-1) {
789c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (c == 0 || n >= sz)
790c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* NUL or not enough free space */
791c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			goto vist_out;
792c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* copy multibyte char */
793c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		sz -= n;
794c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		while (n--)
795c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			*dst++ = *cp++;
796c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto vist_loop;
797c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
798c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (--sz == 0 || (c = (unsigned char)(*cp++)) == 0)
799c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* NUL or not enough free space */
800c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto vist_out;
801737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	if (ISCTRL(c & 0x7F)) {
802c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* C0 or C1 control character or DEL */
803c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (--sz == 0)
804c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* not enough free space for two chars */
805c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			goto vist_out;
806c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		*dst++ = (c & 0x80) ? '$' : '^';
807737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		c = UNCTRL(c & 0x7F);
808c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	} else if (UTFMODE && c > 0x7F) {
809c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* better not try to display broken multibyte chars */
810737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		/* also go easy on the Unicode: no U+FFFD here */
811c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		c = '?';
81203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
813c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	*dst++ = c;
814c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	goto vist_loop;
815c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
816c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser vist_out:
81703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	*dst = '\0';
81803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	afree(buf, ATEMP);
81903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
82003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
82103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef DEBUG
82203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
82303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condradumpchar(struct shf *shf, int c)
82403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
825737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	if (ISCTRL(c & 0x7F)) {
82603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* C0 or C1 control character or DEL */
82703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putc((c & 0x80) ? '$' : '^', shf);
828737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		c = UNCTRL(c & 0x7F);
82903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
83003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	shf_putc(c, shf);
83103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
83203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
83303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* see: wdvarput */
83403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const char *
835c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserdumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
83603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
83703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int c;
83803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
83903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (/* CONSTCOND */ 1) {
84003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		switch(*wp++) {
84103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case EOS:
84203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("EOS", shf);
84303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (--wp);
84403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case ADELIM:
845fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			if (*wp == /*{*/'}') {
84677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes				shf_puts(/*{*/ "]ADELIM(})", shf);
847fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes				return (wp + 1);
848fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes			}
84903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("ADELIM=", shf);
85003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (0)
851a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes				/* FALLTHROUGH */
85203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case CHAR:
853a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			  shf_puts("CHAR=", shf);
85403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumpchar(shf, *wp++);
85503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
85603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case QCHAR:
85703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("QCHAR<", shf);
85803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			c = *wp++;
85903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (quotelevel == 0 ||
86003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    (c == '"' || c == '`' || c == '$' || c == '\\'))
86103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\\', shf);
86203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumpchar(shf, c);
86303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto closeandout;
864a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		case COMASUB:
865a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			shf_puts("COMASUB<", shf);
866a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			goto dumpsub;
86703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case COMSUB:
86803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("COMSUB<", shf);
86903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpsub:
87003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while ((c = *wp++) != 0)
87103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				dumpchar(shf, c);
87203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra closeandout:
87303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('>', shf);
87403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
875a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		case FUNASUB:
876a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			shf_puts("FUNASUB<", shf);
877a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			goto dumpsub;
878c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		case FUNSUB:
879c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			shf_puts("FUNSUB<", shf);
880c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			goto dumpsub;
881811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		case VALSUB:
882811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			shf_puts("VALSUB<", shf);
883811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			goto dumpsub;
88403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case EXPRSUB:
88503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("EXPRSUB<", shf);
88603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto dumpsub;
88703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case OQUOTE:
88877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			shf_fprintf(shf, "OQUOTE{%d" /*}*/, ++quotelevel);
88903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
89003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case CQUOTE:
89177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			shf_fprintf(shf, /*{*/ "%d}CQUOTE", quotelevel);
89203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (quotelevel)
89303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				quotelevel--;
89403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			else
89503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_puts("(err)", shf);
89603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
89703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case OSUBST:
89803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("OSUBST(", shf);
89903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumpchar(shf, *wp++);
90003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(")[", shf);
90103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while ((c = *wp++) != 0)
90203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				dumpchar(shf, c);
90303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('|', shf);
904c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			wp = dumpwdvar_i(shf, wp, 0);
90503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
90603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case CSUBST:
90703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("]CSUBST(", shf);
90803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumpchar(shf, *wp++);
90903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(')', shf);
91003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (wp);
91103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case OPAT:
91203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("OPAT=", shf);
91303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumpchar(shf, *wp++);
91403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
91503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case SPAT:
91603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("SPAT", shf);
91703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
91803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case CPAT:
91903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("CPAT", shf);
92003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
92103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		default:
92203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_fprintf(shf, "INVAL<%u>", (uint8_t)wp[-1]);
92303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
92403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
92503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putc(' ', shf);
92603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
92703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
92803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
92903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condradumpwdvar(struct shf *shf, const char *wp)
93003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
931c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	dumpwdvar_i(shf, wp, 0);
932c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}
933c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
934c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid
935c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserdumpioact(struct shf *shf, struct op *t)
936c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{
937c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	struct ioword **ioact, *iop;
938c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
939c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if ((ioact = t->ioact) == NULL)
940c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		return;
941c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
942c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	shf_puts("{IOACT", shf);
943c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	while ((iop = *ioact++) != NULL) {
944b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes		unsigned short type = iop->ioflag & IOTYPE;
945c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define DT(x) case x: shf_puts(#x, shf); break;
946b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes#define DB(x) if (iop->ioflag & x) shf_puts("|" #x, shf);
947c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
948c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		shf_putc(';', shf);
949c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		switch (type) {
950c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DT(IOREAD)
951c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DT(IOWRITE)
952c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DT(IORDWR)
953c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DT(IOHERE)
954c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DT(IOCAT)
955c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DT(IODUP)
956c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		default:
957c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			shf_fprintf(shf, "unk%d", type);
958c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
959c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DB(IOEVAL)
960c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DB(IOSKIP)
961c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DB(IOCLOB)
962c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DB(IORDUP)
963c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DB(IONAMEXP)
964c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DB(IOBASH)
965c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DB(IOHERESTR)
966c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		DB(IONDELIM)
967b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes		shf_fprintf(shf, ",unit=%d", (int)iop->unit);
968fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes		if (iop->delim && !(iop->ioflag & IONDELIM)) {
969c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			shf_puts(",delim<", shf);
970c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			dumpwdvar(shf, iop->delim);
971c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			shf_putc('>', shf);
972c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
973fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes		if (iop->ioname) {
974b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes			if (iop->ioflag & IONAMEXP) {
975c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shf_puts(",name=", shf);
976fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes				print_value_quoted(shf, iop->ioname);
977c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			} else {
978c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shf_puts(",name<", shf);
979fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes				dumpwdvar(shf, iop->ioname);
980c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shf_putc('>', shf);
981c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			}
982c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
983c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (iop->heredoc) {
984c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			shf_puts(",heredoc=", shf);
985c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			print_value_quoted(shf, iop->heredoc);
986c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
987c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#undef DT
988c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#undef DB
989c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
990c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	shf_putc('}', shf);
99103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
99203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
99303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
99403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condradumptree(struct shf *shf, struct op *t)
99503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
996c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	int i, j;
99703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	const char **w, *name;
99803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct op *t1;
999c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	static int nesting;
100003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
100103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	for (i = 0; i < nesting; ++i)
100203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putc('\t', shf);
100303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	++nesting;
100403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	shf_puts("{tree:" /*}*/, shf);
100503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (t == NULL) {
100603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		name = "(null)";
100703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto out;
100803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
1009c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	dumpioact(shf, t);
101003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	switch (t->type) {
101103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define OPEN(x) case x: name = #x; shf_puts(" {" #x ":", shf); /*}*/
101203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
101303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TCOM)
101403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->vars) {
101503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			i = 0;
101603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = (const char **)t->vars;
101703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w) {
101803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\n', shf);
1019c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				for (j = 0; j < nesting; ++j)
102003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc('\t', shf);
102103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_fprintf(shf, " var%d<", i++);
102203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				dumpwdvar(shf, *w++);
102303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('>', shf);
102403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
102503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
102603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(" #no-vars#", shf);
102703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->args) {
102803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			i = 0;
102903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = t->args;
103003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w) {
103103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\n', shf);
1032c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				for (j = 0; j < nesting; ++j)
103303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc('\t', shf);
103403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_fprintf(shf, " arg%d<", i++);
103503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				dumpwdvar(shf, *w++);
103603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('>', shf);
103703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
103803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
103903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(" #no-args#", shf);
104003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
104103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TEXEC)
104203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpleftandout:
104303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		t = t->left;
104403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpandout:
104503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putc('\n', shf);
104603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		dumptree(shf, t);
104703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
104803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TPAREN)
104903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
105003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TPIPE)
105103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpleftmidrightandout:
105203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putc('\n', shf);
105303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		dumptree(shf, t->left);
105403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* middumprightandout: (unused) */
105503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_fprintf(shf, "/%s:", name);
105603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumprightandout:
105703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		t = t->right;
105803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpandout;
105903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TLIST)
106003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftmidrightandout;
106103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TOR)
106203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftmidrightandout;
106303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TAND)
106403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftmidrightandout;
106503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TBANG)
106603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumprightandout;
106703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TDBRACKET)
106803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		i = 0;
106903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		w = t->args;
107003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*w) {
107103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('\n', shf);
1072c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			for (j = 0; j < nesting; ++j)
107303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\t', shf);
107403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_fprintf(shf, " arg%d<", i++);
107503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumpwdvar(shf, *w++);
107603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('>', shf);
107703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
107803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
107903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TFOR)
108003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpfor:
108103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_fprintf(shf, " str<%s>", t->str);
108203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->vars != NULL) {
108303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			i = 0;
108403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = (const char **)t->vars;
108503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w) {
108603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\n', shf);
1087c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				for (j = 0; j < nesting; ++j)
108803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc('\t', shf);
108903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_fprintf(shf, " var%d<", i++);
109003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				dumpwdvar(shf, *w++);
109103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('>', shf);
109203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
109303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
109403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
109503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TSELECT)
109603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpfor;
109703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TCASE)
109803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_fprintf(shf, " str<%s>", t->str);
109903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		i = 0;
110003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		for (t1 = t->left; t1 != NULL; t1 = t1->right) {
110103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('\n', shf);
1102c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			for (j = 0; j < nesting; ++j)
110303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\t', shf);
110403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_fprintf(shf, " sub%d[(", i);
110503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = (const char **)t1->vars;
110603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w) {
110703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				dumpwdvar(shf, *w);
110803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (w[1] != NULL)
110903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc('|', shf);
111003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				++w;
111103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
111203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(')', shf);
1113c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			dumpioact(shf, t);
111403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('\n', shf);
111503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumptree(shf, t1->left);
111603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_fprintf(shf, " ;%c/%d]", t1->u.charflag, i++);
111703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
111803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
111903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TWHILE)
112003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftmidrightandout;
112103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TUNTIL)
112203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftmidrightandout;
112303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TBRACE)
112403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
112503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TCOPROC)
112603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
112703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TASYNC)
112803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
112903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TFUNCT)
113003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_fprintf(shf, " str<%s> ksh<%s>", t->str,
113177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		    t->u.ksh_func ? Ttrue : Tfalse);
113203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
113303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TTIME)
113403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
113503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TIF)
113603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpif:
113703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putc('\n', shf);
113803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		dumptree(shf, t->left);
113903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		t = t->right;
1140c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		dumpioact(shf, t);
114103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->left != NULL) {
114203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(" /TTHEN:\n", shf);
114303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumptree(shf, t->left);
114403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
114503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->right && t->right->type == TELIF) {
114603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(" /TELIF:", shf);
114703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			t = t->right;
1148c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			dumpioact(shf, t);
114903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto dumpif;
115003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
115103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->right != NULL) {
115203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(" /TELSE:\n", shf);
115303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumptree(shf, t->right);
115403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
115503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
115603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TEOF)
115703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpunexpected:
115877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		shf_puts(Tunexpected, shf);
115903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
116003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TELIF)
116103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpunexpected;
116203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TPAT)
116303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpunexpected;
116403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	default:
116503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		name = "TINVALID";
116603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_fprintf(shf, "{T<%d>:" /*}*/, t->type);
116703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpunexpected;
116803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
116903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#undef OPEN
117003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
117103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra out:
117203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	shf_fprintf(shf, /*{*/ " /%s}\n", name);
117303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	--nesting;
117403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
117503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
1176