1 0 stevel /* 2 356 muffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 0 stevel * Use is subject to license terms. 4 0 stevel */ 5 0 stevel 6 0 stevel /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 0 stevel /* All Rights Reserved */ 8 0 stevel 9 0 stevel /* 10 0 stevel * Copyright (c) 1980 Regents of the University of California. 11 0 stevel * All rights reserved. The Berkeley Software License Agreement 12 0 stevel * specifies the terms and conditions for redistribution. 13 0 stevel */ 14 0 stevel 15 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 16 0 stevel 17 0 stevel #include "sh.h" 18 0 stevel #include "sh.tconst.h" 19 0 stevel 20 0 stevel /* 21 0 stevel * C shell 22 0 stevel */ 23 0 stevel 24 356 muffin void asyntax(struct wordent *, struct wordent *); 25 356 muffin void asyn0(struct wordent *, struct wordent *); 26 356 muffin void asyn3(struct wordent *, struct wordent *); 27 356 muffin void chr_blkfree(char **); 28 356 muffin struct command *syn0(struct wordent *, struct wordent *, int); 29 356 muffin struct command *syn1(struct wordent *, struct wordent *, int); 30 356 muffin struct command *syn1a(struct wordent *, struct wordent *, int); 31 356 muffin struct command *syn1b(struct wordent *, struct wordent *, int); 32 356 muffin struct command *syn2(struct wordent *, struct wordent *, int); 33 356 muffin struct command *syn3(struct wordent *, struct wordent *, int); 34 356 muffin struct wordent *freenod(struct wordent *, struct wordent *); 35 356 muffin 36 0 stevel /* 37 0 stevel * Perform aliasing on the word list lex 38 0 stevel * Do a (very rudimentary) parse to separate into commands. 39 0 stevel * If word 0 of a command has an alias, do it. 40 0 stevel * Repeat a maximum of 20 times. 41 0 stevel */ 42 356 muffin void 43 356 muffin alias(struct wordent *lex) 44 0 stevel { 45 0 stevel int aleft = 21; 46 0 stevel jmp_buf osetexit; 47 0 stevel 48 0 stevel #ifdef TRACE 49 0 stevel tprintf("TRACE- alias()\n"); 50 0 stevel #endif 51 0 stevel getexit(osetexit); 52 0 stevel setexit(); 53 0 stevel if (haderr) { 54 0 stevel resexit(osetexit); 55 0 stevel reset(); 56 0 stevel } 57 0 stevel if (--aleft == 0) 58 0 stevel error("Alias loop"); 59 0 stevel asyntax(lex->next, lex); 60 0 stevel resexit(osetexit); 61 0 stevel } 62 0 stevel 63 356 muffin void 64 356 muffin asyntax(struct wordent *p1, struct wordent *p2) 65 0 stevel { 66 0 stevel #ifdef TRACE 67 0 stevel tprintf("TRACE- asyntax()\n"); 68 0 stevel #endif 69 0 stevel 70 0 stevel while (p1 != p2) 71 0 stevel /* if (any(p1->word[0], ";&\n")) */ /* For char -> tchar */ 72 0 stevel if (p1->word[0] == ';' || 73 0 stevel p1->word[0] == '&' || 74 0 stevel p1->word[0] == '\n') 75 0 stevel p1 = p1->next; 76 0 stevel else { 77 0 stevel asyn0(p1, p2); 78 0 stevel return; 79 0 stevel } 80 0 stevel } 81 0 stevel 82 356 muffin void 83 356 muffin asyn0(struct wordent *p1, struct wordent *p2) 84 0 stevel { 85 356 muffin struct wordent *p; 86 356 muffin int l = 0; 87 0 stevel 88 0 stevel #ifdef TRACE 89 0 stevel tprintf("TRACE- asyn0()\n"); 90 0 stevel #endif 91 0 stevel for (p = p1; p != p2; p = p->next) 92 0 stevel switch (p->word[0]) { 93 0 stevel 94 0 stevel case '(': 95 0 stevel l++; 96 0 stevel continue; 97 0 stevel 98 0 stevel case ')': 99 0 stevel l--; 100 0 stevel if (l < 0) 101 0 stevel error("Too many )'s"); 102 0 stevel continue; 103 0 stevel 104 0 stevel case '>': 105 0 stevel if (p->next != p2 && eq(p->next->word, S_AND /* "&"*/)) 106 0 stevel p = p->next; 107 0 stevel continue; 108 0 stevel 109 0 stevel case '&': 110 0 stevel case '|': 111 0 stevel case ';': 112 0 stevel case '\n': 113 0 stevel if (l != 0) 114 0 stevel continue; 115 0 stevel asyn3(p1, p); 116 0 stevel asyntax(p->next, p2); 117 0 stevel return; 118 0 stevel } 119 0 stevel if (l == 0) 120 0 stevel asyn3(p1, p2); 121 0 stevel } 122 0 stevel 123 356 muffin void 124 356 muffin asyn3(struct wordent *p1, struct wordent *p2) 125 0 stevel { 126 356 muffin struct varent *ap; 127 0 stevel struct wordent alout; 128 356 muffin bool redid; 129 0 stevel 130 0 stevel #ifdef TRACE 131 0 stevel tprintf("TRACE- asyn3()\n"); 132 0 stevel #endif 133 0 stevel if (p1 == p2) 134 0 stevel return; 135 0 stevel if (p1->word[0] == '(') { 136 0 stevel for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 137 0 stevel if (p2 == p1) 138 0 stevel return; 139 0 stevel if (p2 == p1->next) 140 0 stevel return; 141 0 stevel asyn0(p1->next, p2); 142 0 stevel return; 143 0 stevel } 144 0 stevel ap = adrof1(p1->word, &aliases); 145 0 stevel if (ap == 0) 146 0 stevel return; 147 0 stevel alhistp = p1->prev; 148 0 stevel alhistt = p2; 149 0 stevel alvec = ap->vec; 150 0 stevel redid = lex(&alout); 151 0 stevel alhistp = alhistt = 0; 152 0 stevel alvec = 0; 153 0 stevel if (err) { 154 0 stevel freelex(&alout); 155 0 stevel error("%s", gettext(err)); 156 0 stevel } 157 0 stevel if (p1->word[0] && eq(p1->word, alout.next->word)) { 158 0 stevel tchar *cp = alout.next->word; 159 0 stevel 160 559 nakanon alout.next->word = strspl(S_TOPBIT /* "\200" */, cp); 161 559 nakanon xfree(cp); 162 0 stevel } 163 0 stevel p1 = freenod(p1, redid ? p2 : p1->next); 164 0 stevel if (alout.next != &alout) { 165 0 stevel p1->next->prev = alout.prev->prev; 166 0 stevel alout.prev->prev->next = p1->next; 167 0 stevel alout.next->prev = p1; 168 0 stevel p1->next = alout.next; 169 559 nakanon xfree(alout.prev->word); 170 559 nakanon xfree(alout.prev); 171 0 stevel } 172 0 stevel reset(); /* throw! */ 173 0 stevel } 174 0 stevel 175 0 stevel struct wordent * 176 356 muffin freenod(struct wordent *p1, struct wordent *p2) 177 0 stevel { 178 356 muffin struct wordent *retp = p1->prev; 179 0 stevel 180 0 stevel #ifdef TRACE 181 0 stevel tprintf("TRACE- freenod()\n"); 182 0 stevel #endif 183 0 stevel while (p1 != p2) { 184 559 nakanon xfree(p1->word); 185 0 stevel p1 = p1->next; 186 559 nakanon xfree(p1->prev); 187 0 stevel } 188 0 stevel retp->next = p2; 189 0 stevel p2->prev = retp; 190 0 stevel return (retp); 191 0 stevel } 192 0 stevel 193 0 stevel #define PHERE 1 194 0 stevel #define PIN 2 195 0 stevel #define POUT 4 196 0 stevel #define PDIAG 8 197 0 stevel 198 0 stevel /* 199 0 stevel * syntax 200 0 stevel * empty 201 0 stevel * syn0 202 0 stevel */ 203 0 stevel struct command * 204 356 muffin syntax(struct wordent *p1, struct wordent *p2, int flags) 205 0 stevel { 206 0 stevel #ifdef TRACE 207 0 stevel tprintf("TRACE- syntax()\n"); 208 0 stevel #endif 209 0 stevel 210 0 stevel while (p1 != p2) 211 0 stevel /* if (any(p1->word[0], ";&\n")) */ /* for char -> tchar */ 212 0 stevel if (p1->word[0] == ';' || 213 0 stevel p1->word[0] == '&' || 214 0 stevel p1->word[0] == '\n') 215 0 stevel p1 = p1->next; 216 0 stevel else 217 0 stevel return (syn0(p1, p2, flags)); 218 0 stevel return (0); 219 0 stevel } 220 0 stevel 221 0 stevel /* 222 0 stevel * syn0 223 0 stevel * syn1 224 0 stevel * syn1 & syntax 225 0 stevel */ 226 0 stevel struct command * 227 356 muffin syn0(struct wordent *p1, struct wordent *p2, int flags) 228 0 stevel { 229 356 muffin struct wordent *p; 230 356 muffin struct command *t, *t1; 231 0 stevel int l; 232 0 stevel 233 0 stevel #ifdef TRACE 234 0 stevel tprintf("TRACE- syn0()\n"); 235 0 stevel #endif 236 0 stevel l = 0; 237 0 stevel for (p = p1; p != p2; p = p->next) 238 0 stevel switch (p->word[0]) { 239 0 stevel 240 0 stevel case '(': 241 0 stevel l++; 242 0 stevel continue; 243 0 stevel 244 0 stevel case ')': 245 0 stevel l--; 246 0 stevel if (l < 0) 247 0 stevel seterr("Too many )'s"); 248 0 stevel continue; 249 0 stevel 250 0 stevel case '|': 251 0 stevel if (p->word[1] == '|') 252 0 stevel continue; 253 0 stevel /* fall into ... */ 254 0 stevel 255 0 stevel case '>': 256 559 nakanon if (p->next != p2 && eq(p->next->word, S_AND /* "&" */)) 257 0 stevel p = p->next; 258 0 stevel continue; 259 0 stevel 260 0 stevel case '&': 261 0 stevel if (l != 0) 262 0 stevel break; 263 0 stevel if (p->word[1] == '&') 264 0 stevel continue; 265 0 stevel t1 = syn1(p1, p, flags); 266 0 stevel if (t1->t_dtyp == TLST || 267 559 nakanon t1->t_dtyp == TAND || 268 559 nakanon t1->t_dtyp == TOR) { 269 559 nakanon t = (struct command *)xcalloc(1, sizeof (*t)); 270 0 stevel t->t_dtyp = TPAR; 271 0 stevel t->t_dflg = FAND|FINT; 272 0 stevel t->t_dspr = t1; 273 0 stevel t1 = t; 274 0 stevel } else 275 0 stevel t1->t_dflg |= FAND|FINT; 276 559 nakanon t = (struct command *)xcalloc(1, sizeof (*t)); 277 0 stevel t->t_dtyp = TLST; 278 0 stevel t->t_dflg = 0; 279 0 stevel t->t_dcar = t1; 280 0 stevel t->t_dcdr = syntax(p, p2, flags); 281 559 nakanon return (t); 282 0 stevel } 283 0 stevel if (l == 0) 284 0 stevel return (syn1(p1, p2, flags)); 285 0 stevel seterr("Too many ('s"); 286 0 stevel return (0); 287 0 stevel } 288 0 stevel 289 0 stevel /* 290 0 stevel * syn1 291 0 stevel * syn1a 292 0 stevel * syn1a ; syntax 293 0 stevel */ 294 0 stevel struct command * 295 356 muffin syn1(struct wordent *p1, struct wordent *p2, int flags) 296 0 stevel { 297 356 muffin struct wordent *p; 298 356 muffin struct command *t; 299 0 stevel int l; 300 0 stevel 301 0 stevel #ifdef TRACE 302 0 stevel tprintf("TRACE- syn1()\n"); 303 0 stevel #endif 304 0 stevel l = 0; 305 0 stevel for (p = p1; p != p2; p = p->next) 306 0 stevel switch (p->word[0]) { 307 0 stevel 308 0 stevel case '(': 309 0 stevel l++; 310 0 stevel continue; 311 0 stevel 312 0 stevel case ')': 313 0 stevel l--; 314 0 stevel continue; 315 0 stevel 316 0 stevel case ';': 317 0 stevel case '\n': 318 0 stevel if (l != 0) 319 0 stevel break; 320 559 nakanon t = (struct command *)xcalloc(1, sizeof (*t)); 321 0 stevel t->t_dtyp = TLST; 322 0 stevel t->t_dcar = syn1a(p1, p, flags); 323 0 stevel t->t_dcdr = syntax(p->next, p2, flags); 324 0 stevel if (t->t_dcdr == 0) 325 0 stevel t->t_dcdr = t->t_dcar, t->t_dcar = 0; 326 0 stevel return (t); 327 0 stevel } 328 0 stevel return (syn1a(p1, p2, flags)); 329 0 stevel } 330 0 stevel 331 0 stevel /* 332 0 stevel * syn1a 333 0 stevel * syn1b 334 0 stevel * syn1b || syn1a 335 0 stevel */ 336 0 stevel struct command * 337 356 muffin syn1a(struct wordent *p1, struct wordent *p2, int flags) 338 0 stevel { 339 356 muffin struct wordent *p; 340 356 muffin struct command *t; 341 356 muffin int l = 0; 342 0 stevel 343 0 stevel #ifdef TRACE 344 0 stevel tprintf("TRACE- syn1a()\n"); 345 0 stevel #endif 346 0 stevel for (p = p1; p != p2; p = p->next) 347 0 stevel switch (p->word[0]) { 348 0 stevel 349 0 stevel case '(': 350 0 stevel l++; 351 0 stevel continue; 352 0 stevel 353 0 stevel case ')': 354 0 stevel l--; 355 0 stevel continue; 356 0 stevel 357 0 stevel case '|': 358 0 stevel if (p->word[1] != '|') 359 0 stevel continue; 360 0 stevel if (l == 0) { 361 559 nakanon t = (struct command *)xcalloc(1, sizeof (*t)); 362 0 stevel t->t_dtyp = TOR; 363 0 stevel t->t_dcar = syn1b(p1, p, flags); 364 0 stevel t->t_dcdr = syn1a(p->next, p2, flags); 365 0 stevel t->t_dflg = 0; 366 0 stevel return (t); 367 0 stevel } 368 0 stevel continue; 369 0 stevel } 370 0 stevel return (syn1b(p1, p2, flags)); 371 0 stevel } 372 0 stevel 373 0 stevel /* 374 0 stevel * syn1b 375 0 stevel * syn2 376 0 stevel * syn2 && syn1b 377 0 stevel */ 378 0 stevel struct command * 379 356 muffin syn1b(struct wordent *p1, struct wordent *p2, int flags) 380 0 stevel { 381 356 muffin struct wordent *p; 382 356 muffin struct command *t; 383 356 muffin int l = 0; 384 0 stevel 385 0 stevel #ifdef TRACE 386 0 stevel tprintf("TRACE- syn1b()\n"); 387 0 stevel #endif 388 0 stevel l = 0; 389 0 stevel for (p = p1; p != p2; p = p->next) 390 0 stevel switch (p->word[0]) { 391 0 stevel 392 0 stevel case '(': 393 0 stevel l++; 394 0 stevel continue; 395 0 stevel 396 0 stevel case ')': 397 0 stevel l--; 398 0 stevel continue; 399 0 stevel 400 0 stevel case '&': 401 0 stevel if (p->word[1] == '&' && l == 0) { 402 559 nakanon t = (struct command *)xcalloc(1, sizeof (*t)); 403 0 stevel t->t_dtyp = TAND; 404 0 stevel t->t_dcar = syn2(p1, p, flags); 405 0 stevel t->t_dcdr = syn1b(p->next, p2, flags); 406 0 stevel t->t_dflg = 0; 407 0 stevel return (t); 408 0 stevel } 409 0 stevel continue; 410 0 stevel } 411 0 stevel return (syn2(p1, p2, flags)); 412 0 stevel } 413 0 stevel 414 0 stevel /* 415 0 stevel * syn2 416 0 stevel * syn3 417 0 stevel * syn3 | syn2 418 0 stevel * syn3 |& syn2 419 0 stevel */ 420 0 stevel struct command * 421 356 muffin syn2(struct wordent *p1, struct wordent *p2, int flags) 422 0 stevel { 423 356 muffin struct wordent *p, *pn; 424 356 muffin struct command *t; 425 356 muffin int l = 0; 426 0 stevel int f; 427 0 stevel 428 0 stevel #ifdef TRACE 429 0 stevel tprintf("TRACE- syn2()\n"); 430 0 stevel #endif 431 0 stevel for (p = p1; p != p2; p = p->next) 432 0 stevel switch (p->word[0]) { 433 0 stevel 434 0 stevel case '(': 435 0 stevel l++; 436 0 stevel continue; 437 0 stevel 438 0 stevel case ')': 439 0 stevel l--; 440 0 stevel continue; 441 0 stevel 442 0 stevel case '|': 443 0 stevel if (l != 0) 444 0 stevel continue; 445 559 nakanon t = (struct command *)xcalloc(1, sizeof (*t)); 446 0 stevel f = flags | POUT; 447 0 stevel pn = p->next; 448 0 stevel if (pn != p2 && pn->word[0] == '&') { 449 0 stevel f |= PDIAG; 450 0 stevel t->t_dflg |= FDIAG; 451 0 stevel } 452 0 stevel t->t_dtyp = TFIL; 453 0 stevel t->t_dcar = syn3(p1, p, f); 454 0 stevel if (pn != p2 && pn->word[0] == '&') 455 0 stevel p = pn; 456 0 stevel t->t_dcdr = syn2(p->next, p2, flags | PIN); 457 0 stevel return (t); 458 0 stevel } 459 0 stevel return (syn3(p1, p2, flags)); 460 0 stevel } 461 0 stevel 462 0 stevel tchar RELPAR[] = {'<', '>', '(', ')', 0}; /* "<>()" */ 463 0 stevel 464 0 stevel /* 465 0 stevel * syn3 466 0 stevel * ( syn0 ) [ < in ] [ > out ] 467 0 stevel * word word* [ < in ] [ > out ] 468 0 stevel * KEYWORD ( word* ) word* [ < in ] [ > out ] 469 0 stevel * 470 0 stevel * KEYWORD = (@ exit foreach if set switch test while) 471 0 stevel */ 472 0 stevel struct command * 473 356 muffin syn3(struct wordent *p1, struct wordent *p2, int flags) 474 0 stevel { 475 356 muffin struct wordent *p; 476 0 stevel struct wordent *lp, *rp; 477 356 muffin struct command *t; 478 356 muffin int l; 479 0 stevel tchar **av; 480 0 stevel int n, c; 481 0 stevel bool specp = 0; 482 0 stevel 483 0 stevel #ifdef TRACE 484 0 stevel tprintf("TRACE- syn3()\n"); 485 0 stevel #endif 486 0 stevel if (p1 != p2) { 487 0 stevel p = p1; 488 0 stevel again: 489 0 stevel switch (srchx(p->word)) { 490 0 stevel 491 0 stevel case ZELSE: 492 0 stevel p = p->next; 493 0 stevel if (p != p2) 494 0 stevel goto again; 495 0 stevel break; 496 0 stevel 497 0 stevel case ZEXIT: 498 0 stevel case ZFOREACH: 499 0 stevel case ZIF: 500 0 stevel case ZLET: 501 0 stevel case ZSET: 502 0 stevel case ZSWITCH: 503 0 stevel case ZWHILE: 504 0 stevel specp = 1; 505 0 stevel break; 506 0 stevel } 507 0 stevel } 508 0 stevel n = 0; 509 0 stevel l = 0; 510 0 stevel for (p = p1; p != p2; p = p->next) 511 0 stevel switch (p->word[0]) { 512 0 stevel 513 0 stevel case '(': 514 0 stevel if (specp) 515 0 stevel n++; 516 0 stevel l++; 517 0 stevel continue; 518 0 stevel 519 0 stevel case ')': 520 0 stevel if (specp) 521 0 stevel n++; 522 0 stevel l--; 523 0 stevel continue; 524 0 stevel 525 0 stevel case '>': 526 0 stevel case '<': 527 0 stevel if (l != 0) { 528 0 stevel if (specp) 529 0 stevel n++; 530 0 stevel continue; 531 0 stevel } 532 0 stevel if (p->next == p2) 533 0 stevel continue; 534 0 stevel if (any(p->next->word[0], RELPAR)) 535 0 stevel continue; 536 0 stevel n--; 537 0 stevel continue; 538 0 stevel 539 0 stevel default: 540 0 stevel if (!specp && l != 0) 541 0 stevel continue; 542 0 stevel n++; 543 0 stevel continue; 544 0 stevel } 545 0 stevel if (n < 0) 546 0 stevel n = 0; 547 559 nakanon t = (struct command *)xcalloc(1, sizeof (*t)); 548 559 nakanon av = (tchar **)xcalloc((unsigned)(n + 1), sizeof (tchar **)); 549 0 stevel t->t_dcom = av; 550 0 stevel n = 0; 551 0 stevel if (p2->word[0] == ')') 552 0 stevel t->t_dflg = FPAR; 553 0 stevel lp = 0; 554 0 stevel rp = 0; 555 0 stevel l = 0; 556 0 stevel for (p = p1; p != p2; p = p->next) { 557 0 stevel c = p->word[0]; 558 0 stevel switch (c) { 559 0 stevel 560 0 stevel case '(': 561 0 stevel if (l == 0) { 562 0 stevel if (lp != 0 && !specp) 563 0 stevel seterr("Badly placed ("); 564 0 stevel lp = p->next; 565 0 stevel } 566 0 stevel l++; 567 0 stevel goto savep; 568 0 stevel 569 0 stevel case ')': 570 0 stevel l--; 571 0 stevel if (l == 0) 572 0 stevel rp = p; 573 0 stevel goto savep; 574 0 stevel 575 0 stevel case '>': 576 0 stevel if (l != 0) 577 0 stevel goto savep; 578 0 stevel if (p->word[1] == '>') 579 0 stevel t->t_dflg |= FCAT; 580 559 nakanon if (p->next != p2 && eq(p->next->word, S_AND /* "&" */)) { 581 0 stevel t->t_dflg |= FDIAG, p = p->next; 582 0 stevel if (flags & (POUT|PDIAG)) 583 0 stevel goto badout; 584 0 stevel } 585 559 nakanon if (p->next != p2 && eq(p->next->word, S_EXAS /* "!" */)) 586 0 stevel t->t_dflg |= FANY, p = p->next; 587 0 stevel if (p->next == p2) { 588 0 stevel missfile: 589 0 stevel seterr("Missing name for redirect"); 590 0 stevel continue; 591 0 stevel } 592 0 stevel p = p->next; 593 0 stevel if (any(p->word[0], RELPAR)) 594 0 stevel goto missfile; 595 0 stevel if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit) 596 0 stevel badout: 597 0 stevel seterr("Ambiguous output redirect"); 598 0 stevel else 599 0 stevel t->t_drit = savestr(p->word); 600 0 stevel continue; 601 0 stevel 602 0 stevel case '<': 603 0 stevel if (l != 0) 604 0 stevel goto savep; 605 0 stevel if (p->word[1] == '<') 606 0 stevel t->t_dflg |= FHERE; 607 0 stevel if (p->next == p2) 608 0 stevel goto missfile; 609 0 stevel p = p->next; 610 0 stevel if (any(p->word[0], RELPAR)) 611 0 stevel goto missfile; 612 0 stevel if ((flags & PHERE) && (t->t_dflg & FHERE)) 613 0 stevel seterr("Can't << within ()'s"); 614 0 stevel else if ((flags & PIN) || t->t_dlef) 615 0 stevel seterr("Ambiguous input redirect"); 616 0 stevel else 617 0 stevel t->t_dlef = savestr(p->word); 618 0 stevel continue; 619 0 stevel 620 0 stevel savep: 621 0 stevel if (!specp) 622 0 stevel continue; 623 0 stevel default: 624 0 stevel if (l != 0 && !specp) 625 0 stevel continue; 626 0 stevel if (err == 0) 627 0 stevel av[n] = savestr(p->word); 628 0 stevel n++; 629 0 stevel continue; 630 0 stevel } 631 0 stevel } 632 0 stevel if (lp != 0 && !specp) { 633 0 stevel if (n != 0) 634 0 stevel seterr("Badly placed ()'s"); 635 0 stevel t->t_dtyp = TPAR; 636 0 stevel t->t_dspr = syn0(lp, rp, PHERE); 637 0 stevel } else { 638 0 stevel if (n == 0) 639 0 stevel seterr("Invalid null command"); 640 0 stevel t->t_dtyp = TCOM; 641 0 stevel } 642 0 stevel return (t); 643 0 stevel } 644 0 stevel 645 356 muffin void 646 356 muffin freesyn(struct command *t) 647 0 stevel { 648 0 stevel #ifdef TRACE 649 0 stevel tprintf("TRACE- freesyn()\n"); 650 0 stevel #endif 651 0 stevel if (t == 0) 652 0 stevel return; 653 0 stevel switch (t->t_dtyp) { 654 0 stevel 655 0 stevel case TCOM: 656 0 stevel blkfree(t->t_dcom); 657 0 stevel if (t->cfname) 658 0 stevel xfree(t->cfname); 659 0 stevel if (t->cargs) 660 0 stevel chr_blkfree(t->cargs); 661 0 stevel goto lr; 662 0 stevel 663 0 stevel case TPAR: 664 0 stevel freesyn(t->t_dspr); 665 0 stevel /* fall into ... */ 666 0 stevel 667 0 stevel lr: 668 559 nakanon xfree(t->t_dlef); 669 559 nakanon xfree(t->t_drit); 670 0 stevel break; 671 0 stevel 672 0 stevel case TAND: 673 0 stevel case TOR: 674 0 stevel case TFIL: 675 0 stevel case TLST: 676 0 stevel freesyn(t->t_dcar), freesyn(t->t_dcdr); 677 0 stevel break; 678 0 stevel } 679 559 nakanon xfree(t); 680 0 stevel } 681 0 stevel 682 0 stevel 683 356 muffin void 684 356 muffin chr_blkfree(char **vec) 685 0 stevel { 686 356 muffin char **av; 687 0 stevel 688 0 stevel for (av = vec; *av; av++) 689 0 stevel xfree(*av); 690 0 stevel xfree(vec); 691 0 stevel } 692