tree.c revision 03ebf06f4e1112a0e9533b93062d169232c4cbfe
15155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*	$OpenBSD: tree.c,v 1.19 2008/08/11 21:50:35 jaredy Exp $	*/
25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*-
403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
55155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Thorsten Glaser <tg@mirbsd.org>
65155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
75155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices
85155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission
95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un-
105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify,
115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence.
125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor
155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event
165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect,
175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out
185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such
195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out
205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended.
215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h"
245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.51 2011/09/07 15:24:21 tg Exp $");
265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define INDENT	8
285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void ptree(struct op *, int, struct shf *);
305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void pioact(struct shf *, int, struct ioword *);
3103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const char *wdvarput(struct shf *, const char *, int, int);
325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void vfptreef(struct shf *, int, const char *, va_list);
335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct ioword **iocopy(struct ioword **, Area *);
345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void iofree(struct ioword **, Area *);
355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* "foo& ; bar" and "foo |& ; bar" are invalid */
3703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic bool prevent_semicolon;
3803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * print a command tree
415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruptree(struct op *t, int indent, struct shf *shf)
445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char **w;
465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct ioword **ioact;
475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct op *t1;
4803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int i;
495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Chain:
515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t == NULL)
525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch (t->type) {
545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TCOM:
5503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->vars) {
5603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = (const char **)t->vars;
5703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w)
585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				fptreef(shf, indent, "%S ", *w++);
5903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts("#no-vars# ", shf);
6103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->args) {
6203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = t->args;
6303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w)
645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				fptreef(shf, indent, "%S ", *w++);
6503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts("#no-args# ", shf);
6703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		prevent_semicolon = false;
685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TEXEC:
705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		t = t->left;
715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto Chain;
725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TPAREN:
735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent + 2, "( %T) ", t->left);
745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TPIPE:
765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%T| ", t->left);
775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		t = t->right;
785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto Chain;
795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TLIST:
805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%T%;", t->left);
815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		t = t->right;
825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto Chain;
835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TOR:
845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TAND:
855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%T%s %T",
8603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    t->left, (t->type == TOR) ? "||" : "&&", t->right);
875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TBANG:
895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts("! ", shf);
9003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		prevent_semicolon = false;
915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		t = t->right;
925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto Chain;
9303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TDBRACKET:
9403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		w = t->args;
955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts("[[", shf);
9603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*w)
9703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			fptreef(shf, indent, " %S", *w++);
985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts(" ]] ", shf);
995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TSELECT:
1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TFOR:
10203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fptreef(shf, indent, "%s %s ",
10303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    (t->type == TFOR) ? "for" : Tselect, t->str);
1045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (t->vars != NULL) {
1055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts("in ", shf);
10603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = (const char **)t->vars;
10703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w)
1085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				fptreef(shf, indent, "%S ", *w++);
1095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fptreef(shf, indent, "%;");
1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent + INDENT, "do%N%T", t->left);
1125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%;done ");
1135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TCASE:
1155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "case %S in", t->str);
1165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (t1 = t->left; t1 != NULL; t1 = t1->right) {
1175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fptreef(shf, indent, "%N(");
11803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = (const char **)t1->vars;
11903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w) {
1205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				fptreef(shf, indent, "%S%c", *w,
1215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    (w[1] != NULL) ? '|' : ')');
12203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				++w;
12303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
12403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			fptreef(shf, indent + INDENT, "%N%T%N;%c", t1->left,
12503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    t1->u.charflag);
1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%Nesac ");
1285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
12903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef MKSH_NO_DEPRECATED_WARNING
1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TELIF:
13103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		internal_errorf("TELIF in tree.c:ptree() unexpected");
13203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* FALLTHROUGH */
13303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
13403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TIF:
13503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		i = 2;
13603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto process_TIF;
13703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		do {
13803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			t = t->right;
13903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			i = 0;
14003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			fptreef(shf, indent, "%;");
14103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra process_TIF:
14203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* 5 == strlen("elif ") */
14303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			fptreef(shf, indent + 5 - i, "elif %T" + i, t->left);
1445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t = t->right;
1455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (t->left != NULL) {
1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				fptreef(shf, indent, "%;");
14703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				fptreef(shf, indent + INDENT, "%s%N%T",
14803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    "then", t->left);
1495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
15003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} while (t->right && t->right->type == TELIF);
1515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (t->right != NULL) {
1525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fptreef(shf, indent, "%;");
15303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			fptreef(shf, indent + INDENT, "%s%N%T",
15403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "else", t->right);
1555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%;fi ");
1575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TWHILE:
1595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TUNTIL:
1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* 6 == strlen("while"/"until") */
1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent + 6, "%s %T",
16203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    (t->type == TWHILE) ? "while" : "until",
1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    t->left);
16403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fptreef(shf, indent, "%;");
16503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fptreef(shf, indent + INDENT, "do%N%T", t->right);
1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%;done ");
1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TBRACE:
16903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fptreef(shf, indent + INDENT, "{%N%T", t->left);
1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%;} ");
1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TCOPROC:
1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%T|& ", t->left);
17403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		prevent_semicolon = true;
1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TASYNC:
1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, "%T& ", t->left);
17803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		prevent_semicolon = true;
1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TFUNCT:
18103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fpFUNCTf(shf, indent, tobool(t->u.ksh_func), t->str, t->left);
1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case TTIME:
18403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fptreef(shf, indent, "%s %T", "time", t->left);
1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	default:
1875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts("<botch>", shf);
18803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		prevent_semicolon = false;
1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((ioact = t->ioact) != NULL) {
19203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bool need_nl = false;
1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (*ioact != NULL)
1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			pioact(shf, indent, *ioact++);
1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* Print here documents after everything else... */
19703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		ioact = t->ioact;
19803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*ioact != NULL) {
1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			struct ioword *iop = *ioact++;
2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
20103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* heredoc is NULL when tracing (set -x) */
20203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if ((iop->flag & (IOTYPE | IOHERESTR)) == IOHERE &&
20303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    iop->heredoc) {
20403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\n', shf);
2055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_puts(iop->heredoc, shf);
2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				fptreef(shf, indent, "%s",
20703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    iop->flag & IONDELIM ? "<<" :
2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    evalstr(iop->delim, 0));
20903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				need_nl = true;
2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
2115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
21203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
21303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Last delimiter must be followed by a newline (this
21403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * often leads to an extra blank line, but it's not
21503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * worth worrying about)
2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (need_nl)
21803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('\n', shf);
2195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
2215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
2235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querupioact(struct shf *shf, int indent, struct ioword *iop)
2245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
2255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int flag = iop->flag;
2265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int type = flag & IOTYPE;
2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int expected;
2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 :
2305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (type == IOCAT || type == IOWRITE) ? 1 :
2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit :
2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    iop->unit + 1;
2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (iop->unit != expected)
2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_fprintf(shf, "%d", iop->unit);
2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch (type) {
2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case IOREAD:
23803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_puts("<", shf);
2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case IOHERE:
2415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts(flag & IOSKIP ? "<<-" : "<<", shf);
2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case IOCAT:
24403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_puts(">>", shf);
2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case IOWRITE:
24703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_puts(flag & IOCLOB ? ">|" : ">", shf);
2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case IORDWR:
25003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_puts("<>", shf);
2515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case IODUP:
2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts(flag & IORDUP ? "<&" : ">&", shf);
2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
25603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* name/delim are NULL when printing syntax errors */
2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (type == IOHERE) {
2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (iop->delim)
25903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			fptreef(shf, indent, "%S ", iop->delim);
2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
26103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(' ', shf);
2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else if (iop->name)
2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fptreef(shf, indent, (iop->flag & IONAMEXP) ? "%s " : "%S ",
2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    iop->name);
26503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	prevent_semicolon = false;
2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* variant of fputs for ptreef and wdstrip */
26903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const char *
27003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrawdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
27203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int c;
2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*-
27503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * problems:
2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	`...` -> $(...)
2775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	'foo' -> "foo"
27803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 *	x${foo:-"hi"} -> x${foo:-hi} unless WDS_TPUTS
27903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 *	x${foo:-'hi'} -> x${foo:-hi} unless WDS_KEEPQ
2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * could change encoding to:
2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	OQUOTE ["'] ... CQUOTE ["']
2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	COMSUB [(`] ...\0	(handle $ ` \ and maybe " in `...` case)
2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
28403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (/* CONSTCOND */ 1)
2855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (*wp++) {
2865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case EOS:
28703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (--wp);
2885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case ADELIM:
2895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CHAR:
29003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			c = *wp++;
29103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if ((opmode & WDS_MAGIC) &&
29203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    (ISMAGIC(c) || c == '[' || c == NOT ||
29303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    c == '-' || c == ']' || c == '*' || c == '?'))
29403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc(MAGIC, shf);
29503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(c, shf);
2965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
29703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case QCHAR: {
29803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bool doq;
29903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
3005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			c = *wp++;
30103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			doq = (c == '"' || c == '`' || c == '$' || c == '\\');
30203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (opmode & WDS_TPUTS) {
30303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (quotelevel == 0)
30403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					doq = true;
30503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			} else {
30603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (!(opmode & WDS_KEEPQ))
30703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					doq = false;
30803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
30903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (doq)
31003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\\', shf);
31103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(c, shf);
3125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
31303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
3145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case COMSUB:
3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts("$(", shf);
31603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while ((c = *wp++) != 0)
31703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc(c, shf);
31803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(')', shf);
3195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
3205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case EXPRSUB:
3215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts("$((", shf);
32203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while ((c = *wp++) != 0)
32303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc(c, shf);
3245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts("))", shf);
3255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
3265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case OQUOTE:
32703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (opmode & WDS_TPUTS) {
32803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				quotelevel++;
32903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('"', shf);
33003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
3315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
3325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CQUOTE:
33303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (opmode & WDS_TPUTS) {
33403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (quotelevel)
33503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					quotelevel--;
33603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('"', shf);
33703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
3385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
3395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case OSUBST:
34003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('$', shf);
3415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*wp++ == '{')
34203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('{', shf);
3435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while ((c = *wp++) != 0)
34403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc(c, shf);
34503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			wp = wdvarput(shf, wp, 0, opmode);
3465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
3475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CSUBST:
3485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*wp++ == '}')
34903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('}', shf);
35003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (wp);
3515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case OPAT:
35203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (opmode & WDS_MAGIC) {
35303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc(MAGIC, shf);
35403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putchar(*wp++ | 0x80, shf);
35503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			} else {
35603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putchar(*wp++, shf);
35703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('(', shf);
35803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
3595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
3605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SPAT:
36103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			c = '|';
36203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (0)
3635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CPAT:
36403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				c = /*(*/ ')';
36503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (opmode & WDS_MAGIC)
36603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc(MAGIC, shf);
36703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(c, shf);
3685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
3705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * this is the _only_ way to reliably handle
3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * variable args with an ANSI compiler
3755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
3765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* VARARGS */
37703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querufptreef(struct shf *shf, int indent, const char *fmt, ...)
3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
3815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_start(va, fmt);
3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vfptreef(shf, indent, fmt, va);
3845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_end(va);
3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* VARARGS */
3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar *
38903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrasnptreef(char *s, ssize_t n, const char *fmt, ...)
3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct shf shf;
3935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_sopen(s, n, SHF_WR | (s ? 0 : SHF_DYNAMIC), &shf);
3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_start(va, fmt);
3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vfptreef(&shf, 0, fmt, va);
3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_end(va);
3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
40003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* shf_sclose NUL terminates */
40103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (shf_sclose(&shf));
4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int c;
4085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((c = *fmt++)) {
4105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '%') {
4115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			switch ((c = *fmt++)) {
4125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'c':
41303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* character (octet, probably) */
41403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putchar(va_arg(va, int), shf);
4155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
4165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 's':
41703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* string */
4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_puts(va_arg(va, char *), shf);
4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
42003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case 'S':
42103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* word */
42203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				wdvarput(shf, va_arg(va, char *), 0, WDS_TPUTS);
4235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
42403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case 'd':
42503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* signed decimal */
4265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_fprintf(shf, "%d", va_arg(va, int));
4275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
42803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case 'u':
42903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* unsigned decimal */
4305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_fprintf(shf, "%u", va_arg(va, unsigned int));
4315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
43203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case 'T':
43303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* format tree */
4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ptree(va_arg(va, struct op *), indent, shf);
43503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				goto dont_trash_prevent_semicolon;
43603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case ';':
43703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* newline or ; */
43803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case 'N':
43903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* newline or space */
4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (shf->flags & SHF_STRING) {
44103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					if (c == ';' && !prevent_semicolon)
44203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						shf_putc(';', shf);
44303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc(' ', shf);
4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else {
4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					int i;
4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
44703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc('\n', shf);
44803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					i = indent;
44903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					while (i >= 8) {
45003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						shf_putc('\t', shf);
45103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						i -= 8;
45203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					}
45303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					while (i--)
45403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						shf_putc(' ', shf);
4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'R':
45803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* I/O redirection */
4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				pioact(shf, indent, va_arg(va, struct ioword *));
4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			default:
46203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc(c, shf);
4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
46603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(c, shf);
46703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		prevent_semicolon = false;
46803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dont_trash_prevent_semicolon:
46903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		;
4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * copy tree (for function definition)
4755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct op *
4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutcopy(struct op *t, Area *ap)
4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct op *r;
4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char **tw;
4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char **rw;
4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t == NULL)
4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (NULL);
4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r = alloc(sizeof(struct op), ap);
4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r->type = t->type;
4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r->u.evalflags = t->u.evalflags;
4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->type == TCASE)
4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		r->str = wdcopy(t->str, ap);
4935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
4945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strdupx(r->str, t->str, ap);
4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->vars == NULL)
4975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		r->vars = NULL;
4985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else {
49903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		tw = (const char **)t->vars;
50003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*tw)
50103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			++tw;
50203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		rw = r->vars = alloc2(tw - (const char **)t->vars + 1,
5035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    sizeof(*tw), ap);
50403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		tw = (const char **)t->vars;
50503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*tw)
5065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*rw++ = wdcopy(*tw++, ap);
5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*rw = NULL;
5085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->args == NULL)
5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		r->args = NULL;
5125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else {
51303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		tw = t->args;
51403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*tw)
51503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			++tw;
51603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		r->args = (const char **)(rw = alloc2(tw - t->args + 1,
5175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    sizeof(*tw), ap));
51803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		tw = t->args;
51903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*tw)
5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*rw++ = wdcopy(*tw++, ap);
5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*rw = NULL;
5225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap);
5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r->left = tcopy(t->left, ap);
5275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r->right = tcopy(t->right, ap);
5285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	r->lineno = t->lineno;
5295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (r);
5315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
5325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar *
5345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruwdcopy(const char *wp, Area *ap)
5355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
53603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t len;
53703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
53803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	len = wdscan(wp, EOS) - wp;
5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (memcpy(alloc(len, ap), wp, len));
5405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
5415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* return the position of prefix c in wp plus 1 */
5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruconst char *
5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruwdscan(const char *wp, int c)
5455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
5465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int nest = 0;
5475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
54803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (/* CONSTCOND */ 1)
5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (*wp++) {
5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case EOS:
5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (wp);
5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case ADELIM:
5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == ADELIM)
5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (wp + 1);
5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* FALLTHROUGH */
5565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CHAR:
5575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case QCHAR:
5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			wp++;
5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case COMSUB:
5615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case EXPRSUB:
5625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (*wp++ != 0)
5635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				;
5645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case OQUOTE:
5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CQUOTE:
5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case OSUBST:
5695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nest++;
5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (*wp++ != '\0')
5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				;
5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CSUBST:
5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			wp++;
5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == CSUBST && nest == 0)
5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (wp);
5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nest--;
5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case OPAT:
5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nest++;
5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			wp++;
5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case SPAT:
5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CPAT:
5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c == wp[-1] && nest == 0)
5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (wp);
5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (wp[-1] == CPAT)
5885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				nest--;
5895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		default:
5915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			internal_warningf(
5925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    "wdscan: unknown char 0x%x (carrying on)",
5935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    wp[-1]);
5945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
5955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
5965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
59703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
59803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * return a copy of wp without any of the mark up characters and with
59903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * quote characters (" ' \) stripped. (string is allocated from ATEMP)
6005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
6015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar *
60203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrawdstrip(const char *wp, int opmode)
6035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct shf shf;
6055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_sopen(NULL, 32, SHF_WR | SHF_DYNAMIC, &shf);
60703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	wdvarput(&shf, wp, 0, opmode);
60803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* shf_sclose NUL terminates */
60903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (shf_sclose(&shf));
6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct ioword **
6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruiocopy(struct ioword **iow, Area *ap)
6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct ioword **ior;
6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
61803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ior = iow;
61903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (*ior)
62003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++ior;
62103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ior = alloc2(ior - iow + 1, sizeof(struct ioword *), ap);
6225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (i = 0; iow[i] != NULL; i++) {
6245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct ioword *p, *q;
6255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p = iow[i];
6275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		q = alloc(sizeof(struct ioword), ap);
6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ior[i] = q;
6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*q = *p;
6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->name != NULL)
6315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			q->name = wdcopy(p->name, ap);
6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->delim != NULL)
6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			q->delim = wdcopy(p->delim, ap);
6345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->heredoc != NULL)
6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			strdupx(q->heredoc, p->heredoc, ap);
6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ior[i] = NULL;
6385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (ior);
6405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
6435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * free tree (for function definition)
6445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
6455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
6465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutfree(struct op *t, Area *ap)
6475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char **w;
6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t == NULL)
6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->str != NULL)
6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(t->str, ap);
6555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->vars != NULL) {
6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (w = t->vars; *w != NULL; w++)
6585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(*w, ap);
6595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(t->vars, ap);
6605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->args != NULL) {
66303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*XXX we assume the caller is right */
6645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		union mksh_ccphack cw;
66503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
6665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		cw.ro = t->args;
6675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (w = cw.rw; *w != NULL; w++)
6685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(*w, ap);
6695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(t->args, ap);
6705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->ioact != NULL)
6735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		iofree(t->ioact, ap);
6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tfree(t->left, ap);
6765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tfree(t->right, ap);
6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(t, ap);
6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruiofree(struct ioword **iow, Area *ap)
6835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct ioword **iop;
6855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct ioword *p;
6865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
68703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	iop = iow;
68803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while ((p = *iop++) != NULL) {
6895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->name != NULL)
6905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(p->name, ap);
6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->delim != NULL)
6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(p->delim, ap);
6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->heredoc != NULL)
6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(p->heredoc, ap);
6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(p, ap);
6965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(iow, ap);
6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
69903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
70003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
70103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy CondrafpFUNCTf(struct shf *shf, int i, bool isksh, const char *k, struct op *v)
70203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
70303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (isksh)
70403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fptreef(shf, i, "%s %s %T", Tfunction, k, v);
70503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else
70603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fptreef(shf, i, "%s() %T", k, v);
70703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
70803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
70903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
71003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* for jobs.c */
71103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
71203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravistree(char *dst, size_t sz, struct op *t)
71303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
71403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int c;
71503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char *cp, *buf;
71603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
71703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	buf = alloc(sz, ATEMP);
71803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	snptreef(buf, sz, "%T", t);
71903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	cp = buf;
72003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while ((c = *cp++)) {
72103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (((c & 0x60) == 0) || ((c & 0x7F) == 0x7F)) {
72203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* C0 or C1 control character or DEL */
72303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (!--sz)
72403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				break;
72503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			*dst++ = (c & 0x80) ? '$' : '^';
72603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			c = (c & 0x7F) ^ 0x40;
72703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
72803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!--sz)
72903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
73003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		*dst++ = c;
73103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
73203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	*dst = '\0';
73303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	afree(buf, ATEMP);
73403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
73503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
73603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef DEBUG
73703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
73803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condradumpchar(struct shf *shf, int c)
73903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
74003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (((c & 0x60) == 0) || ((c & 0x7F) == 0x7F)) {
74103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* C0 or C1 control character or DEL */
74203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putc((c & 0x80) ? '$' : '^', shf);
74303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		c = (c & 0x7F) ^ 0x40;
74403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
74503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	shf_putc(c, shf);
74603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
74703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
74803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* see: wdvarput */
74903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const char *
75003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condradumpwdvar_(struct shf *shf, const char *wp, int quotelevel)
75103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
75203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int c;
75303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
75403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (/* CONSTCOND */ 1) {
75503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		switch(*wp++) {
75603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case EOS:
75703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("EOS", shf);
75803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (--wp);
75903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case ADELIM:
76003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("ADELIM=", shf);
76103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (0)
76203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case CHAR:
76303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_puts("CHAR=", shf);
76403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumpchar(shf, *wp++);
76503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
76603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case QCHAR:
76703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("QCHAR<", shf);
76803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			c = *wp++;
76903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (quotelevel == 0 ||
77003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    (c == '"' || c == '`' || c == '$' || c == '\\'))
77103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\\', shf);
77203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumpchar(shf, c);
77303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto closeandout;
77403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case COMSUB:
77503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("COMSUB<", shf);
77603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpsub:
77703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while ((c = *wp++) != 0)
77803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				dumpchar(shf, c);
77903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra closeandout:
78003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('>', shf);
78103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
78203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case EXPRSUB:
78303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("EXPRSUB<", shf);
78403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto dumpsub;
78503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case OQUOTE:
78603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_fprintf(shf, "OQUOTE{%d", ++quotelevel);
78703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
78803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case CQUOTE:
78903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_fprintf(shf, "%d}CQUOTE", quotelevel);
79003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (quotelevel)
79103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				quotelevel--;
79203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			else
79303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_puts("(err)", shf);
79403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
79503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case OSUBST:
79603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("OSUBST(", shf);
79703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumpchar(shf, *wp++);
79803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(")[", shf);
79903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while ((c = *wp++) != 0)
80003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				dumpchar(shf, c);
80103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('|', shf);
80203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			wp = dumpwdvar_(shf, wp, 0);
80303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
80403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case CSUBST:
80503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("]CSUBST(", shf);
80603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumpchar(shf, *wp++);
80703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(')', shf);
80803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (wp);
80903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case OPAT:
81003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("OPAT=", shf);
81103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumpchar(shf, *wp++);
81203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
81303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case SPAT:
81403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("SPAT", shf);
81503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
81603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case CPAT:
81703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts("CPAT", shf);
81803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
81903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		default:
82003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_fprintf(shf, "INVAL<%u>", (uint8_t)wp[-1]);
82103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
82203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
82303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putc(' ', shf);
82403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
82503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
82603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
82703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condradumpwdvar(struct shf *shf, const char *wp)
82803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
82903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	dumpwdvar_(shf, wp, 0);
83003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
83103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
83203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
83303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condradumptree(struct shf *shf, struct op *t)
83403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
83503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int i;
83603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	const char **w, *name;
83703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct op *t1;
83803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	static int nesting = 0;
83903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
84003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	for (i = 0; i < nesting; ++i)
84103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putc('\t', shf);
84203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	++nesting;
84303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	shf_puts("{tree:" /*}*/, shf);
84403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (t == NULL) {
84503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		name = "(null)";
84603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto out;
84703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
84803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	switch (t->type) {
84903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define OPEN(x) case x: name = #x; shf_puts(" {" #x ":", shf); /*}*/
85003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
85103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TCOM)
85203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->vars) {
85303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			i = 0;
85403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = (const char **)t->vars;
85503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w) {
85603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\n', shf);
85703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				for (int j = 0; j < nesting; ++j)
85803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc('\t', shf);
85903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_fprintf(shf, " var%d<", i++);
86003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				dumpwdvar(shf, *w++);
86103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('>', shf);
86203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
86303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
86403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(" #no-vars#", shf);
86503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->args) {
86603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			i = 0;
86703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = t->args;
86803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w) {
86903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\n', shf);
87003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				for (int j = 0; j < nesting; ++j)
87103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc('\t', shf);
87203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_fprintf(shf, " arg%d<", i++);
87303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				dumpwdvar(shf, *w++);
87403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('>', shf);
87503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
87603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
87703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(" #no-args#", shf);
87803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
87903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TEXEC)
88003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpleftandout:
88103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		t = t->left;
88203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpandout:
88303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putc('\n', shf);
88403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		dumptree(shf, t);
88503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
88603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TPAREN)
88703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
88803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TPIPE)
88903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpleftmidrightandout:
89003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putc('\n', shf);
89103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		dumptree(shf, t->left);
89203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* middumprightandout: (unused) */
89303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_fprintf(shf, "/%s:", name);
89403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumprightandout:
89503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		t = t->right;
89603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpandout;
89703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TLIST)
89803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftmidrightandout;
89903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TOR)
90003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftmidrightandout;
90103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TAND)
90203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftmidrightandout;
90303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TBANG)
90403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumprightandout;
90503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TDBRACKET)
90603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		i = 0;
90703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		w = t->args;
90803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (*w) {
90903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('\n', shf);
91003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			for (int j = 0; j < nesting; ++j)
91103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\t', shf);
91203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_fprintf(shf, " arg%d<", i++);
91303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumpwdvar(shf, *w++);
91403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('>', shf);
91503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
91603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
91703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TFOR)
91803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpfor:
91903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_fprintf(shf, " str<%s>", t->str);
92003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->vars != NULL) {
92103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			i = 0;
92203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = (const char **)t->vars;
92303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w) {
92403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\n', shf);
92503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				for (int j = 0; j < nesting; ++j)
92603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc('\t', shf);
92703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_fprintf(shf, " var%d<", i++);
92803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				dumpwdvar(shf, *w++);
92903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('>', shf);
93003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
93103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
93203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
93303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TSELECT)
93403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpfor;
93503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TCASE)
93603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_fprintf(shf, " str<%s>", t->str);
93703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		i = 0;
93803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		for (t1 = t->left; t1 != NULL; t1 = t1->right) {
93903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('\n', shf);
94003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			for (int j = 0; j < nesting; ++j)
94103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\t', shf);
94203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_fprintf(shf, " sub%d[(", i);
94303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			w = (const char **)t1->vars;
94403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (*w) {
94503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				dumpwdvar(shf, *w);
94603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (w[1] != NULL)
94703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc('|', shf);
94803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				++w;
94903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
95003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc(')', shf);
95103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_putc('\n', shf);
95203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumptree(shf, t1->left);
95303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_fprintf(shf, " ;%c/%d]", t1->u.charflag, i++);
95403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
95503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
95603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TWHILE)
95703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftmidrightandout;
95803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TUNTIL)
95903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftmidrightandout;
96003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TBRACE)
96103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
96203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TCOPROC)
96303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
96403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TASYNC)
96503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
96603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TFUNCT)
96703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_fprintf(shf, " str<%s> ksh<%s>", t->str,
96803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    t->u.ksh_func ? "yes" : "no");
96903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
97003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TTIME)
97103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpleftandout;
97203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TIF)
97303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpif:
97403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putc('\n', shf);
97503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		dumptree(shf, t->left);
97603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		t = t->right;
97703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->left != NULL) {
97803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(" /TTHEN:\n", shf);
97903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumptree(shf, t->left);
98003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
98103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->right && t->right->type == TELIF) {
98203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(" /TELIF:", shf);
98303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			t = t->right;
98403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto dumpif;
98503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
98603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (t->right != NULL) {
98703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(" /TELSE:\n", shf);
98803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			dumptree(shf, t->right);
98903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
99003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
99103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TEOF)
99203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dumpunexpected:
99303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_puts("unexpected", shf);
99403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
99503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TELIF)
99603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpunexpected;
99703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	OPEN(TPAT)
99803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpunexpected;
99903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	default:
100003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		name = "TINVALID";
100103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_fprintf(shf, "{T<%d>:" /*}*/, t->type);
100203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto dumpunexpected;
100303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
100403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#undef OPEN
100503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
100603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra out:
100703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	shf_fprintf(shf, /*{*/ " /%s}\n", name);
100803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	--nesting;
100903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
101003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
1011