1 1.10 christos /* $NetBSD: tree.c,v 1.10 2021/09/16 19:44:01 christos Exp $ */ 2 1.2 tls 3 1.1 jtc /* 4 1.1 jtc * command tree climbing 5 1.1 jtc */ 6 1.4 agc #include <sys/cdefs.h> 7 1.4 agc 8 1.4 agc #ifndef lint 9 1.10 christos __RCSID("$NetBSD: tree.c,v 1.10 2021/09/16 19:44:01 christos Exp $"); 10 1.4 agc #endif 11 1.4 agc 12 1.1 jtc 13 1.1 jtc #include "sh.h" 14 1.1 jtc 15 1.1 jtc #define INDENT 4 16 1.1 jtc 17 1.1 jtc #define tputc(c, shf) shf_putchar(c, shf); 18 1.1 jtc static void ptree ARGS((struct op *t, int indent, struct shf *f)); 19 1.1 jtc static void pioact ARGS((struct shf *f, int indent, struct ioword *iop)); 20 1.1 jtc static void tputC ARGS((int c, struct shf *shf)); 21 1.1 jtc static void tputS ARGS((char *wp, struct shf *shf)); 22 1.1 jtc static void vfptreef ARGS((struct shf *shf, int indent, const char *fmt, va_list va)); 23 1.1 jtc static struct ioword **iocopy ARGS((struct ioword **iow, Area *ap)); 24 1.1 jtc static void iofree ARGS((struct ioword **iow, Area *ap)); 25 1.1 jtc 26 1.1 jtc /* 27 1.1 jtc * print a command tree 28 1.1 jtc */ 29 1.1 jtc 30 1.1 jtc static void 31 1.1 jtc ptree(t, indent, shf) 32 1.9 kamil struct op *t; 33 1.1 jtc int indent; 34 1.9 kamil struct shf *shf; 35 1.1 jtc { 36 1.9 kamil char **w; 37 1.1 jtc struct ioword **ioact; 38 1.1 jtc struct op *t1; 39 1.1 jtc 40 1.1 jtc Chain: 41 1.1 jtc if (t == NULL) 42 1.1 jtc return; 43 1.1 jtc switch (t->type) { 44 1.1 jtc case TCOM: 45 1.1 jtc if (t->vars) 46 1.1 jtc for (w = t->vars; *w != NULL; ) 47 1.1 jtc fptreef(shf, indent, "%S ", *w++); 48 1.1 jtc else 49 1.1 jtc fptreef(shf, indent, "#no-vars# "); 50 1.1 jtc if (t->args) 51 1.1 jtc for (w = t->args; *w != NULL; ) 52 1.1 jtc fptreef(shf, indent, "%S ", *w++); 53 1.1 jtc else 54 1.1 jtc fptreef(shf, indent, "#no-args# "); 55 1.1 jtc break; 56 1.1 jtc case TEXEC: 57 1.3 hubertf #if 0 /* ?not useful - can't be called? */ 58 1.3 hubertf /* Print original vars */ 59 1.3 hubertf if (t->left->vars) 60 1.3 hubertf for (w = t->left->vars; *w != NULL; ) 61 1.3 hubertf fptreef(shf, indent, "%S ", *w++); 62 1.3 hubertf else 63 1.3 hubertf fptreef(shf, indent, "#no-vars# "); 64 1.3 hubertf /* Print expanded vars */ 65 1.3 hubertf if (t->args) 66 1.3 hubertf for (w = t->args; *w != NULL; ) 67 1.3 hubertf fptreef(shf, indent, "%s ", *w++); 68 1.3 hubertf else 69 1.3 hubertf fptreef(shf, indent, "#no-args# "); 70 1.3 hubertf /* Print original io */ 71 1.3 hubertf t = t->left; 72 1.3 hubertf #else 73 1.1 jtc t = t->left; 74 1.1 jtc goto Chain; 75 1.3 hubertf #endif 76 1.1 jtc case TPAREN: 77 1.1 jtc fptreef(shf, indent + 2, "( %T) ", t->left); 78 1.1 jtc break; 79 1.1 jtc case TPIPE: 80 1.1 jtc fptreef(shf, indent, "%T| ", t->left); 81 1.1 jtc t = t->right; 82 1.1 jtc goto Chain; 83 1.1 jtc case TLIST: 84 1.1 jtc fptreef(shf, indent, "%T%;", t->left); 85 1.1 jtc t = t->right; 86 1.1 jtc goto Chain; 87 1.1 jtc case TOR: 88 1.1 jtc case TAND: 89 1.1 jtc fptreef(shf, indent, "%T%s %T", 90 1.1 jtc t->left, (t->type==TOR) ? "||" : "&&", t->right); 91 1.1 jtc break; 92 1.1 jtc case TBANG: 93 1.1 jtc fptreef(shf, indent, "! "); 94 1.1 jtc t = t->right; 95 1.1 jtc goto Chain; 96 1.1 jtc case TDBRACKET: 97 1.1 jtc { 98 1.1 jtc int i; 99 1.1 jtc 100 1.1 jtc fptreef(shf, indent, "[["); 101 1.1 jtc for (i = 0; t->args[i]; i++) 102 1.1 jtc fptreef(shf, indent, " %S", t->args[i]); 103 1.1 jtc fptreef(shf, indent, " ]] "); 104 1.1 jtc break; 105 1.1 jtc } 106 1.1 jtc #ifdef KSH 107 1.1 jtc case TSELECT: 108 1.1 jtc fptreef(shf, indent, "select %s ", t->str); 109 1.1 jtc #endif /* KSH */ 110 1.10 christos /*FALLTHROUGH*/ 111 1.1 jtc case TFOR: 112 1.1 jtc if (t->type == TFOR) 113 1.1 jtc fptreef(shf, indent, "for %s ", t->str); 114 1.1 jtc if (t->vars != NULL) { 115 1.1 jtc fptreef(shf, indent, "in "); 116 1.1 jtc for (w = t->vars; *w; ) 117 1.1 jtc fptreef(shf, indent, "%S ", *w++); 118 1.1 jtc fptreef(shf, indent, "%;"); 119 1.1 jtc } 120 1.1 jtc fptreef(shf, indent + INDENT, "do%N%T", t->left); 121 1.1 jtc fptreef(shf, indent, "%;done "); 122 1.1 jtc break; 123 1.1 jtc case TCASE: 124 1.1 jtc fptreef(shf, indent, "case %S in", t->str); 125 1.1 jtc for (t1 = t->left; t1 != NULL; t1 = t1->right) { 126 1.1 jtc fptreef(shf, indent, "%N("); 127 1.1 jtc for (w = t1->vars; *w != NULL; w++) 128 1.1 jtc fptreef(shf, indent, "%S%c", *w, 129 1.1 jtc (w[1] != NULL) ? '|' : ')'); 130 1.1 jtc fptreef(shf, indent + INDENT, "%;%T%N;;", t1->left); 131 1.1 jtc } 132 1.1 jtc fptreef(shf, indent, "%Nesac "); 133 1.1 jtc break; 134 1.1 jtc case TIF: 135 1.1 jtc case TELIF: 136 1.1 jtc /* 3 == strlen("if ") */ 137 1.1 jtc fptreef(shf, indent + 3, "if %T", t->left); 138 1.1 jtc for (;;) { 139 1.1 jtc t = t->right; 140 1.1 jtc if (t->left != NULL) { 141 1.1 jtc fptreef(shf, indent, "%;"); 142 1.1 jtc fptreef(shf, indent + INDENT, "then%N%T", 143 1.1 jtc t->left); 144 1.1 jtc } 145 1.1 jtc if (t->right == NULL || t->right->type != TELIF) 146 1.1 jtc break; 147 1.1 jtc t = t->right; 148 1.1 jtc fptreef(shf, indent, "%;"); 149 1.1 jtc /* 5 == strlen("elif ") */ 150 1.1 jtc fptreef(shf, indent + 5, "elif %T", t->left); 151 1.1 jtc } 152 1.1 jtc if (t->right != NULL) { 153 1.1 jtc fptreef(shf, indent, "%;"); 154 1.1 jtc fptreef(shf, indent + INDENT, "else%;%T", t->right); 155 1.1 jtc } 156 1.1 jtc fptreef(shf, indent, "%;fi "); 157 1.1 jtc break; 158 1.1 jtc case TWHILE: 159 1.1 jtc case TUNTIL: 160 1.1 jtc /* 6 == strlen("while"/"until") */ 161 1.1 jtc fptreef(shf, indent + 6, "%s %T", 162 1.1 jtc (t->type==TWHILE) ? "while" : "until", 163 1.1 jtc t->left); 164 1.1 jtc fptreef(shf, indent, "%;do"); 165 1.1 jtc fptreef(shf, indent + INDENT, "%;%T", t->right); 166 1.1 jtc fptreef(shf, indent, "%;done "); 167 1.1 jtc break; 168 1.1 jtc case TBRACE: 169 1.1 jtc fptreef(shf, indent + INDENT, "{%;%T", t->left); 170 1.1 jtc fptreef(shf, indent, "%;} "); 171 1.1 jtc break; 172 1.1 jtc case TCOPROC: 173 1.1 jtc fptreef(shf, indent, "%T|& ", t->left); 174 1.1 jtc break; 175 1.1 jtc case TASYNC: 176 1.1 jtc fptreef(shf, indent, "%T& ", t->left); 177 1.1 jtc break; 178 1.1 jtc case TFUNCT: 179 1.3 hubertf fptreef(shf, indent, 180 1.3 hubertf t->u.ksh_func ? "function %s %T" : "%s() %T", 181 1.3 hubertf t->str, t->left); 182 1.1 jtc break; 183 1.1 jtc case TTIME: 184 1.1 jtc fptreef(shf, indent, "time %T", t->left); 185 1.1 jtc break; 186 1.1 jtc default: 187 1.1 jtc fptreef(shf, indent, "<botch>"); 188 1.1 jtc break; 189 1.1 jtc } 190 1.1 jtc if ((ioact = t->ioact) != NULL) { 191 1.1 jtc int need_nl = 0; 192 1.1 jtc 193 1.1 jtc while (*ioact != NULL) 194 1.1 jtc pioact(shf, indent, *ioact++); 195 1.1 jtc /* Print here documents after everything else... */ 196 1.1 jtc for (ioact = t->ioact; *ioact != NULL; ) { 197 1.1 jtc struct ioword *iop = *ioact++; 198 1.1 jtc 199 1.3 hubertf /* heredoc is 0 when tracing (set -x) */ 200 1.3 hubertf if ((iop->flag & IOTYPE) == IOHERE && iop->heredoc) { 201 1.1 jtc tputc('\n', shf); 202 1.3 hubertf shf_puts(iop->heredoc, shf); 203 1.3 hubertf fptreef(shf, indent, "%s", 204 1.3 hubertf evalstr(iop->delim, 0)); 205 1.1 jtc need_nl = 1; 206 1.1 jtc } 207 1.1 jtc } 208 1.1 jtc /* Last delimiter must be followed by a newline (this often 209 1.1 jtc * leads to an extra blank line, but its not worth worrying 210 1.1 jtc * about) 211 1.1 jtc */ 212 1.1 jtc if (need_nl) 213 1.1 jtc tputc('\n', shf); 214 1.1 jtc } 215 1.1 jtc } 216 1.1 jtc 217 1.1 jtc static void 218 1.1 jtc pioact(shf, indent, iop) 219 1.9 kamil struct shf *shf; 220 1.1 jtc int indent; 221 1.9 kamil struct ioword *iop; 222 1.1 jtc { 223 1.1 jtc int flag = iop->flag; 224 1.1 jtc int type = flag & IOTYPE; 225 1.1 jtc int expected; 226 1.1 jtc 227 1.1 jtc expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 228 1.1 jtc : (type == IOCAT || type == IOWRITE) ? 1 229 1.1 jtc : (type == IODUP && (iop->unit == !(flag & IORDUP))) ? 230 1.1 jtc iop->unit 231 1.1 jtc : iop->unit + 1; 232 1.1 jtc if (iop->unit != expected) 233 1.1 jtc tputc('0' + iop->unit, shf); 234 1.1 jtc 235 1.1 jtc switch (type) { 236 1.1 jtc case IOREAD: 237 1.1 jtc fptreef(shf, indent, "< "); 238 1.1 jtc break; 239 1.1 jtc case IOHERE: 240 1.1 jtc if (flag&IOSKIP) 241 1.1 jtc fptreef(shf, indent, "<<- "); 242 1.1 jtc else 243 1.1 jtc fptreef(shf, indent, "<< "); 244 1.1 jtc break; 245 1.1 jtc case IOCAT: 246 1.1 jtc fptreef(shf, indent, ">> "); 247 1.1 jtc break; 248 1.1 jtc case IOWRITE: 249 1.1 jtc if (flag&IOCLOB) 250 1.1 jtc fptreef(shf, indent, ">| "); 251 1.1 jtc else 252 1.1 jtc fptreef(shf, indent, "> "); 253 1.1 jtc break; 254 1.1 jtc case IORDWR: 255 1.1 jtc fptreef(shf, indent, "<> "); 256 1.1 jtc break; 257 1.1 jtc case IODUP: 258 1.1 jtc if (flag & IORDUP) 259 1.1 jtc fptreef(shf, indent, "<&"); 260 1.1 jtc else 261 1.1 jtc fptreef(shf, indent, ">&"); 262 1.1 jtc break; 263 1.1 jtc } 264 1.1 jtc /* name/delim are 0 when printing syntax errors */ 265 1.1 jtc if (type == IOHERE) { 266 1.1 jtc if (iop->delim) 267 1.1 jtc fptreef(shf, indent, "%S ", iop->delim); 268 1.1 jtc } else if (iop->name) 269 1.1 jtc fptreef(shf, indent, (iop->flag & IONAMEXP) ? "%s " : "%S ", 270 1.1 jtc iop->name); 271 1.1 jtc } 272 1.1 jtc 273 1.1 jtc 274 1.1 jtc /* 275 1.1 jtc * variants of fputc, fputs for ptreef and snptreef 276 1.1 jtc */ 277 1.1 jtc 278 1.1 jtc static void 279 1.1 jtc tputC(c, shf) 280 1.9 kamil int c; 281 1.9 kamil struct shf *shf; 282 1.1 jtc { 283 1.1 jtc if ((c&0x60) == 0) { /* C0|C1 */ 284 1.1 jtc tputc((c&0x80) ? '$' : '^', shf); 285 1.1 jtc tputc(((c&0x7F)|0x40), shf); 286 1.1 jtc } else if ((c&0x7F) == 0x7F) { /* DEL */ 287 1.1 jtc tputc((c&0x80) ? '$' : '^', shf); 288 1.1 jtc tputc('?', shf); 289 1.1 jtc } else 290 1.1 jtc tputc(c, shf); 291 1.1 jtc } 292 1.1 jtc 293 1.1 jtc static void 294 1.1 jtc tputS(wp, shf) 295 1.9 kamil char *wp; 296 1.9 kamil struct shf *shf; 297 1.1 jtc { 298 1.9 kamil int c, quoted=0; 299 1.1 jtc 300 1.3 hubertf /* problems: 301 1.3 hubertf * `...` -> $(...) 302 1.3 hubertf * 'foo' -> "foo" 303 1.3 hubertf * could change encoding to: 304 1.3 hubertf * OQUOTE ["'] ... CQUOTE ["'] 305 1.3 hubertf * COMSUB [(`] ...\0 (handle $ ` \ and maybe " in `...` case) 306 1.3 hubertf */ 307 1.1 jtc while (1) 308 1.1 jtc switch ((c = *wp++)) { 309 1.1 jtc case EOS: 310 1.1 jtc return; 311 1.1 jtc case CHAR: 312 1.1 jtc tputC(*wp++, shf); 313 1.1 jtc break; 314 1.1 jtc case QCHAR: 315 1.1 jtc c = *wp++; 316 1.1 jtc if (!quoted || (c == '"' || c == '`' || c == '$')) 317 1.1 jtc tputc('\\', shf); 318 1.1 jtc tputC(c, shf); 319 1.1 jtc break; 320 1.1 jtc case COMSUB: 321 1.1 jtc tputc('$', shf); 322 1.1 jtc tputc('(', shf); 323 1.1 jtc while (*wp != 0) 324 1.1 jtc tputC(*wp++, shf); 325 1.1 jtc tputc(')', shf); 326 1.3 hubertf wp++; 327 1.1 jtc break; 328 1.1 jtc case EXPRSUB: 329 1.1 jtc tputc('$', shf); 330 1.1 jtc tputc('(', shf); 331 1.1 jtc tputc('(', shf); 332 1.1 jtc while (*wp != 0) 333 1.1 jtc tputC(*wp++, shf); 334 1.1 jtc tputc(')', shf); 335 1.1 jtc tputc(')', shf); 336 1.3 hubertf wp++; 337 1.1 jtc break; 338 1.1 jtc case OQUOTE: 339 1.1 jtc quoted = 1; 340 1.1 jtc tputc('"', shf); 341 1.1 jtc break; 342 1.1 jtc case CQUOTE: 343 1.1 jtc quoted = 0; 344 1.1 jtc tputc('"', shf); 345 1.1 jtc break; 346 1.1 jtc case OSUBST: 347 1.1 jtc tputc('$', shf); 348 1.3 hubertf if (*wp++ == '{') 349 1.3 hubertf tputc('{', shf); 350 1.1 jtc while ((c = *wp++) != 0) 351 1.1 jtc tputC(c, shf); 352 1.1 jtc break; 353 1.1 jtc case CSUBST: 354 1.3 hubertf if (*wp++ == '}') 355 1.3 hubertf tputc('}', shf); 356 1.1 jtc break; 357 1.1 jtc #ifdef KSH 358 1.1 jtc case OPAT: 359 1.1 jtc tputc(*wp++, shf); 360 1.1 jtc tputc('(', shf); 361 1.1 jtc break; 362 1.1 jtc case SPAT: 363 1.1 jtc tputc('|', shf); 364 1.1 jtc break; 365 1.1 jtc case CPAT: 366 1.1 jtc tputc(')', shf); 367 1.1 jtc break; 368 1.1 jtc #endif /* KSH */ 369 1.1 jtc } 370 1.1 jtc } 371 1.1 jtc 372 1.1 jtc /* 373 1.1 jtc * this is the _only_ way to reliably handle 374 1.1 jtc * variable args with an ANSI compiler 375 1.1 jtc */ 376 1.1 jtc /* VARARGS */ 377 1.1 jtc int 378 1.1 jtc fptreef(struct shf *shf, int indent, const char *fmt, ...) 379 1.1 jtc { 380 1.1 jtc va_list va; 381 1.1 jtc 382 1.7 kamil va_start(va, fmt); 383 1.5 mycroft 384 1.1 jtc vfptreef(shf, indent, fmt, va); 385 1.1 jtc va_end(va); 386 1.1 jtc return 0; 387 1.1 jtc } 388 1.1 jtc 389 1.1 jtc /* VARARGS */ 390 1.1 jtc char * 391 1.1 jtc snptreef(char *s, int n, const char *fmt, ...) 392 1.1 jtc { 393 1.1 jtc va_list va; 394 1.1 jtc struct shf shf; 395 1.1 jtc 396 1.1 jtc shf_sopen(s, n, SHF_WR | (s ? 0 : SHF_DYNAMIC), &shf); 397 1.1 jtc 398 1.7 kamil va_start(va, fmt); 399 1.1 jtc vfptreef(&shf, 0, fmt, va); 400 1.1 jtc va_end(va); 401 1.1 jtc 402 1.1 jtc return shf_sclose(&shf); /* null terminates */ 403 1.1 jtc } 404 1.1 jtc 405 1.1 jtc static void 406 1.1 jtc vfptreef(shf, indent, fmt, va) 407 1.9 kamil struct shf *shf; 408 1.1 jtc int indent; 409 1.1 jtc const char *fmt; 410 1.9 kamil va_list va; 411 1.1 jtc { 412 1.9 kamil int c; 413 1.1 jtc 414 1.1 jtc while ((c = *fmt++)) 415 1.1 jtc if (c == '%') { 416 1.9 kamil long n; 417 1.9 kamil char *p; 418 1.1 jtc int neg; 419 1.1 jtc 420 1.1 jtc switch ((c = *fmt++)) { 421 1.1 jtc case 'c': 422 1.1 jtc tputc(va_arg(va, int), shf); 423 1.1 jtc break; 424 1.1 jtc case 's': 425 1.1 jtc p = va_arg(va, char *); 426 1.1 jtc while (*p) 427 1.1 jtc tputc(*p++, shf); 428 1.1 jtc break; 429 1.1 jtc case 'S': /* word */ 430 1.1 jtc p = va_arg(va, char *); 431 1.1 jtc tputS(p, shf); 432 1.1 jtc break; 433 1.1 jtc case 'd': case 'u': /* decimal */ 434 1.1 jtc n = (c == 'd') ? va_arg(va, int) 435 1.1 jtc : va_arg(va, unsigned int); 436 1.1 jtc neg = c=='d' && n<0; 437 1.1 jtc p = ulton((neg) ? -n : n, 10); 438 1.1 jtc if (neg) 439 1.1 jtc *--p = '-'; 440 1.1 jtc while (*p) 441 1.1 jtc tputc(*p++, shf); 442 1.1 jtc break; 443 1.1 jtc case 'T': /* format tree */ 444 1.1 jtc ptree(va_arg(va, struct op *), indent, shf); 445 1.1 jtc break; 446 1.1 jtc case ';': /* newline or ; */ 447 1.1 jtc case 'N': /* newline or space */ 448 1.1 jtc if (shf->flags & SHF_STRING) { 449 1.1 jtc if (c == ';') 450 1.1 jtc tputc(';', shf); 451 1.1 jtc tputc(' ', shf); 452 1.1 jtc } else { 453 1.1 jtc int i; 454 1.1 jtc 455 1.1 jtc tputc('\n', shf); 456 1.1 jtc for (i = indent; i >= 8; i -= 8) 457 1.1 jtc tputc('\t', shf); 458 1.1 jtc for (; i > 0; --i) 459 1.1 jtc tputc(' ', shf); 460 1.1 jtc } 461 1.1 jtc break; 462 1.1 jtc case 'R': 463 1.1 jtc pioact(shf, indent, va_arg(va, struct ioword *)); 464 1.1 jtc break; 465 1.1 jtc default: 466 1.1 jtc tputc(c, shf); 467 1.1 jtc break; 468 1.1 jtc } 469 1.1 jtc } else 470 1.1 jtc tputc(c, shf); 471 1.1 jtc } 472 1.1 jtc 473 1.1 jtc /* 474 1.1 jtc * copy tree (for function definition) 475 1.1 jtc */ 476 1.1 jtc 477 1.1 jtc struct op * 478 1.1 jtc tcopy(t, ap) 479 1.9 kamil struct op *t; 480 1.1 jtc Area *ap; 481 1.1 jtc { 482 1.9 kamil struct op *r; 483 1.9 kamil char **tw, **rw; 484 1.1 jtc 485 1.1 jtc if (t == NULL) 486 1.1 jtc return NULL; 487 1.1 jtc 488 1.1 jtc r = (struct op *) alloc(sizeof(struct op), ap); 489 1.1 jtc 490 1.1 jtc r->type = t->type; 491 1.1 jtc r->u.evalflags = t->u.evalflags; 492 1.1 jtc 493 1.1 jtc r->str = t->type == TCASE ? wdcopy(t->str, ap) : str_save(t->str, ap); 494 1.1 jtc 495 1.1 jtc if (t->vars == NULL) 496 1.1 jtc r->vars = NULL; 497 1.1 jtc else { 498 1.1 jtc for (tw = t->vars; *tw++ != NULL; ) 499 1.1 jtc ; 500 1.1 jtc rw = r->vars = (char **) 501 1.5 mycroft alloc((tw - t->vars + 1) * sizeof(*tw), ap); 502 1.1 jtc for (tw = t->vars; *tw != NULL; ) 503 1.1 jtc *rw++ = wdcopy(*tw++, ap); 504 1.1 jtc *rw = NULL; 505 1.1 jtc } 506 1.1 jtc 507 1.1 jtc if (t->args == NULL) 508 1.1 jtc r->args = NULL; 509 1.1 jtc else { 510 1.1 jtc for (tw = t->args; *tw++ != NULL; ) 511 1.1 jtc ; 512 1.1 jtc rw = r->args = (char **) 513 1.5 mycroft alloc((tw - t->args + 1) * sizeof(*tw), ap); 514 1.1 jtc for (tw = t->args; *tw != NULL; ) 515 1.1 jtc *rw++ = wdcopy(*tw++, ap); 516 1.1 jtc *rw = NULL; 517 1.1 jtc } 518 1.1 jtc 519 1.1 jtc r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap); 520 1.1 jtc 521 1.1 jtc r->left = tcopy(t->left, ap); 522 1.1 jtc r->right = tcopy(t->right, ap); 523 1.3 hubertf r->lineno = t->lineno; 524 1.1 jtc 525 1.1 jtc return r; 526 1.1 jtc } 527 1.1 jtc 528 1.1 jtc char * 529 1.1 jtc wdcopy(wp, ap) 530 1.1 jtc const char *wp; 531 1.1 jtc Area *ap; 532 1.1 jtc { 533 1.1 jtc size_t len = wdscan(wp, EOS) - wp; 534 1.1 jtc return memcpy(alloc(len, ap), wp, len); 535 1.1 jtc } 536 1.1 jtc 537 1.1 jtc /* return the position of prefix c in wp plus 1 */ 538 1.1 jtc char * 539 1.1 jtc wdscan(wp, c) 540 1.9 kamil const char *wp; 541 1.9 kamil int c; 542 1.1 jtc { 543 1.9 kamil int nest = 0; 544 1.1 jtc 545 1.1 jtc while (1) 546 1.1 jtc switch (*wp++) { 547 1.1 jtc case EOS: 548 1.6 christos return (char *) __UNCONST(wp); 549 1.1 jtc case CHAR: 550 1.1 jtc case QCHAR: 551 1.1 jtc wp++; 552 1.1 jtc break; 553 1.1 jtc case COMSUB: 554 1.1 jtc case EXPRSUB: 555 1.1 jtc while (*wp++ != 0) 556 1.1 jtc ; 557 1.1 jtc break; 558 1.1 jtc case OQUOTE: 559 1.1 jtc case CQUOTE: 560 1.1 jtc break; 561 1.1 jtc case OSUBST: 562 1.1 jtc nest++; 563 1.1 jtc while (*wp++ != '\0') 564 1.1 jtc ; 565 1.1 jtc break; 566 1.1 jtc case CSUBST: 567 1.3 hubertf wp++; 568 1.1 jtc if (c == CSUBST && nest == 0) 569 1.6 christos return (char *) __UNCONST(wp); 570 1.1 jtc nest--; 571 1.1 jtc break; 572 1.1 jtc #ifdef KSH 573 1.1 jtc case OPAT: 574 1.1 jtc nest++; 575 1.1 jtc wp++; 576 1.1 jtc break; 577 1.1 jtc case SPAT: 578 1.1 jtc case CPAT: 579 1.1 jtc if (c == wp[-1] && nest == 0) 580 1.6 christos return (char *) __UNCONST(wp); 581 1.1 jtc if (wp[-1] == CPAT) 582 1.1 jtc nest--; 583 1.1 jtc break; 584 1.1 jtc #endif /* KSH */ 585 1.3 hubertf default: 586 1.3 hubertf internal_errorf(0, 587 1.3 hubertf "wdscan: unknown char 0x%x (carrying on)", 588 1.3 hubertf wp[-1]); 589 1.3 hubertf } 590 1.3 hubertf } 591 1.3 hubertf 592 1.3 hubertf /* return a copy of wp without any of the mark up characters and 593 1.3 hubertf * with quote characters (" ' \) stripped. 594 1.3 hubertf * (string is allocated from ATEMP) 595 1.3 hubertf */ 596 1.3 hubertf char * 597 1.3 hubertf wdstrip(wp) 598 1.3 hubertf const char *wp; 599 1.3 hubertf { 600 1.3 hubertf struct shf shf; 601 1.3 hubertf int c; 602 1.3 hubertf 603 1.3 hubertf shf_sopen((char *) 0, 32, SHF_WR | SHF_DYNAMIC, &shf); 604 1.3 hubertf 605 1.3 hubertf /* problems: 606 1.3 hubertf * `...` -> $(...) 607 1.3 hubertf * x${foo:-"hi"} -> x${foo:-hi} 608 1.3 hubertf * x${foo:-'hi'} -> x${foo:-hi} 609 1.3 hubertf */ 610 1.3 hubertf while (1) 611 1.3 hubertf switch ((c = *wp++)) { 612 1.3 hubertf case EOS: 613 1.3 hubertf return shf_sclose(&shf); /* null terminates */ 614 1.3 hubertf case CHAR: 615 1.3 hubertf case QCHAR: 616 1.3 hubertf shf_putchar(*wp++, &shf); 617 1.3 hubertf break; 618 1.3 hubertf case COMSUB: 619 1.3 hubertf shf_putchar('$', &shf); 620 1.3 hubertf shf_putchar('(', &shf); 621 1.3 hubertf while (*wp != 0) 622 1.3 hubertf shf_putchar(*wp++, &shf); 623 1.3 hubertf shf_putchar(')', &shf); 624 1.3 hubertf break; 625 1.3 hubertf case EXPRSUB: 626 1.3 hubertf shf_putchar('$', &shf); 627 1.3 hubertf shf_putchar('(', &shf); 628 1.3 hubertf shf_putchar('(', &shf); 629 1.3 hubertf while (*wp != 0) 630 1.3 hubertf shf_putchar(*wp++, &shf); 631 1.3 hubertf shf_putchar(')', &shf); 632 1.3 hubertf shf_putchar(')', &shf); 633 1.3 hubertf break; 634 1.3 hubertf case OQUOTE: 635 1.3 hubertf break; 636 1.3 hubertf case CQUOTE: 637 1.3 hubertf break; 638 1.3 hubertf case OSUBST: 639 1.3 hubertf shf_putchar('$', &shf); 640 1.3 hubertf if (*wp++ == '{') 641 1.3 hubertf shf_putchar('{', &shf); 642 1.3 hubertf while ((c = *wp++) != 0) 643 1.3 hubertf shf_putchar(c, &shf); 644 1.3 hubertf break; 645 1.3 hubertf case CSUBST: 646 1.3 hubertf if (*wp++ == '}') 647 1.3 hubertf shf_putchar('}', &shf); 648 1.3 hubertf break; 649 1.3 hubertf #ifdef KSH 650 1.3 hubertf case OPAT: 651 1.3 hubertf shf_putchar(*wp++, &shf); 652 1.3 hubertf shf_putchar('(', &shf); 653 1.3 hubertf break; 654 1.3 hubertf case SPAT: 655 1.3 hubertf shf_putchar('|', &shf); 656 1.3 hubertf break; 657 1.3 hubertf case CPAT: 658 1.3 hubertf shf_putchar(')', &shf); 659 1.3 hubertf break; 660 1.3 hubertf #endif /* KSH */ 661 1.1 jtc } 662 1.1 jtc } 663 1.1 jtc 664 1.1 jtc static struct ioword ** 665 1.1 jtc iocopy(iow, ap) 666 1.9 kamil struct ioword **iow; 667 1.1 jtc Area *ap; 668 1.1 jtc { 669 1.9 kamil struct ioword **ior; 670 1.9 kamil int i; 671 1.1 jtc 672 1.1 jtc for (ior = iow; *ior++ != NULL; ) 673 1.1 jtc ; 674 1.5 mycroft ior = (struct ioword **) alloc((ior - iow + 1) * sizeof(*ior), ap); 675 1.1 jtc 676 1.1 jtc for (i = 0; iow[i] != NULL; i++) { 677 1.9 kamil struct ioword *p, *q; 678 1.1 jtc 679 1.1 jtc p = iow[i]; 680 1.1 jtc q = (struct ioword *) alloc(sizeof(*p), ap); 681 1.1 jtc ior[i] = q; 682 1.1 jtc *q = *p; 683 1.1 jtc if (p->name != (char *) 0) 684 1.1 jtc q->name = wdcopy(p->name, ap); 685 1.1 jtc if (p->delim != (char *) 0) 686 1.1 jtc q->delim = wdcopy(p->delim, ap); 687 1.3 hubertf if (p->heredoc != (char *) 0) 688 1.3 hubertf q->heredoc = str_save(p->heredoc, ap); 689 1.1 jtc } 690 1.1 jtc ior[i] = NULL; 691 1.1 jtc 692 1.1 jtc return ior; 693 1.1 jtc } 694 1.1 jtc 695 1.1 jtc /* 696 1.1 jtc * free tree (for function definition) 697 1.1 jtc */ 698 1.1 jtc 699 1.1 jtc void 700 1.1 jtc tfree(t, ap) 701 1.9 kamil struct op *t; 702 1.1 jtc Area *ap; 703 1.1 jtc { 704 1.9 kamil char **w; 705 1.1 jtc 706 1.1 jtc if (t == NULL) 707 1.1 jtc return; 708 1.1 jtc 709 1.1 jtc if (t->str != NULL) 710 1.1 jtc afree((void*)t->str, ap); 711 1.1 jtc 712 1.1 jtc if (t->vars != NULL) { 713 1.1 jtc for (w = t->vars; *w != NULL; w++) 714 1.1 jtc afree((void*)*w, ap); 715 1.1 jtc afree((void*)t->vars, ap); 716 1.1 jtc } 717 1.1 jtc 718 1.1 jtc if (t->args != NULL) { 719 1.1 jtc for (w = t->args; *w != NULL; w++) 720 1.1 jtc afree((void*)*w, ap); 721 1.1 jtc afree((void*)t->args, ap); 722 1.1 jtc } 723 1.1 jtc 724 1.1 jtc if (t->ioact != NULL) 725 1.1 jtc iofree(t->ioact, ap); 726 1.1 jtc 727 1.1 jtc tfree(t->left, ap); 728 1.1 jtc tfree(t->right, ap); 729 1.1 jtc 730 1.1 jtc afree((void*)t, ap); 731 1.1 jtc } 732 1.1 jtc 733 1.1 jtc static void 734 1.1 jtc iofree(iow, ap) 735 1.1 jtc struct ioword **iow; 736 1.1 jtc Area *ap; 737 1.1 jtc { 738 1.9 kamil struct ioword **iop; 739 1.9 kamil struct ioword *p; 740 1.1 jtc 741 1.1 jtc for (iop = iow; (p = *iop++) != NULL; ) { 742 1.1 jtc if (p->name != NULL) 743 1.1 jtc afree((void*)p->name, ap); 744 1.3 hubertf if (p->delim != NULL) 745 1.3 hubertf afree((void*)p->delim, ap); 746 1.3 hubertf if (p->heredoc != NULL) 747 1.3 hubertf afree((void*)p->heredoc, ap); 748 1.1 jtc afree((void*)p, ap); 749 1.1 jtc } 750 1.1 jtc } 751