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