17c478bd9Sstevel@tonic-gate /* 26c02b4a4Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 137c478bd9Sstevel@tonic-gate */ 147c478bd9Sstevel@tonic-gate 157c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 167c478bd9Sstevel@tonic-gate 177c478bd9Sstevel@tonic-gate #include "sh.h" 187c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 197c478bd9Sstevel@tonic-gate 207c478bd9Sstevel@tonic-gate /* 217c478bd9Sstevel@tonic-gate * C shell 227c478bd9Sstevel@tonic-gate */ 237c478bd9Sstevel@tonic-gate 246c02b4a4Smuffin void asyntax(struct wordent *, struct wordent *); 256c02b4a4Smuffin void asyn0(struct wordent *, struct wordent *); 266c02b4a4Smuffin void asyn3(struct wordent *, struct wordent *); 276c02b4a4Smuffin void chr_blkfree(char **); 286c02b4a4Smuffin struct command *syn0(struct wordent *, struct wordent *, int); 296c02b4a4Smuffin struct command *syn1(struct wordent *, struct wordent *, int); 306c02b4a4Smuffin struct command *syn1a(struct wordent *, struct wordent *, int); 316c02b4a4Smuffin struct command *syn1b(struct wordent *, struct wordent *, int); 326c02b4a4Smuffin struct command *syn2(struct wordent *, struct wordent *, int); 336c02b4a4Smuffin struct command *syn3(struct wordent *, struct wordent *, int); 346c02b4a4Smuffin struct wordent *freenod(struct wordent *, struct wordent *); 356c02b4a4Smuffin 367c478bd9Sstevel@tonic-gate /* 377c478bd9Sstevel@tonic-gate * Perform aliasing on the word list lex 387c478bd9Sstevel@tonic-gate * Do a (very rudimentary) parse to separate into commands. 397c478bd9Sstevel@tonic-gate * If word 0 of a command has an alias, do it. 407c478bd9Sstevel@tonic-gate * Repeat a maximum of 20 times. 417c478bd9Sstevel@tonic-gate */ 426c02b4a4Smuffin void 436c02b4a4Smuffin alias(struct wordent *lex) 447c478bd9Sstevel@tonic-gate { 457c478bd9Sstevel@tonic-gate int aleft = 21; 467c478bd9Sstevel@tonic-gate jmp_buf osetexit; 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate #ifdef TRACE 497c478bd9Sstevel@tonic-gate tprintf("TRACE- alias()\n"); 507c478bd9Sstevel@tonic-gate #endif 517c478bd9Sstevel@tonic-gate getexit(osetexit); 527c478bd9Sstevel@tonic-gate setexit(); 537c478bd9Sstevel@tonic-gate if (haderr) { 547c478bd9Sstevel@tonic-gate resexit(osetexit); 557c478bd9Sstevel@tonic-gate reset(); 567c478bd9Sstevel@tonic-gate } 577c478bd9Sstevel@tonic-gate if (--aleft == 0) 587c478bd9Sstevel@tonic-gate error("Alias loop"); 597c478bd9Sstevel@tonic-gate asyntax(lex->next, lex); 607c478bd9Sstevel@tonic-gate resexit(osetexit); 617c478bd9Sstevel@tonic-gate } 627c478bd9Sstevel@tonic-gate 636c02b4a4Smuffin void 646c02b4a4Smuffin asyntax(struct wordent *p1, struct wordent *p2) 657c478bd9Sstevel@tonic-gate { 667c478bd9Sstevel@tonic-gate #ifdef TRACE 677c478bd9Sstevel@tonic-gate tprintf("TRACE- asyntax()\n"); 687c478bd9Sstevel@tonic-gate #endif 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate while (p1 != p2) 717c478bd9Sstevel@tonic-gate /* if (any(p1->word[0], ";&\n")) */ /* For char -> tchar */ 727c478bd9Sstevel@tonic-gate if (p1->word[0] == ';' || 737c478bd9Sstevel@tonic-gate p1->word[0] == '&' || 747c478bd9Sstevel@tonic-gate p1->word[0] == '\n') 757c478bd9Sstevel@tonic-gate p1 = p1->next; 767c478bd9Sstevel@tonic-gate else { 777c478bd9Sstevel@tonic-gate asyn0(p1, p2); 787c478bd9Sstevel@tonic-gate return; 797c478bd9Sstevel@tonic-gate } 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate 826c02b4a4Smuffin void 836c02b4a4Smuffin asyn0(struct wordent *p1, struct wordent *p2) 847c478bd9Sstevel@tonic-gate { 856c02b4a4Smuffin struct wordent *p; 866c02b4a4Smuffin int l = 0; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate #ifdef TRACE 897c478bd9Sstevel@tonic-gate tprintf("TRACE- asyn0()\n"); 907c478bd9Sstevel@tonic-gate #endif 917c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 927c478bd9Sstevel@tonic-gate switch (p->word[0]) { 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate case '(': 957c478bd9Sstevel@tonic-gate l++; 967c478bd9Sstevel@tonic-gate continue; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate case ')': 997c478bd9Sstevel@tonic-gate l--; 1007c478bd9Sstevel@tonic-gate if (l < 0) 1017c478bd9Sstevel@tonic-gate error("Too many )'s"); 1027c478bd9Sstevel@tonic-gate continue; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate case '>': 1057c478bd9Sstevel@tonic-gate if (p->next != p2 && eq(p->next->word, S_AND /* "&"*/)) 1067c478bd9Sstevel@tonic-gate p = p->next; 1077c478bd9Sstevel@tonic-gate continue; 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate case '&': 1107c478bd9Sstevel@tonic-gate case '|': 1117c478bd9Sstevel@tonic-gate case ';': 1127c478bd9Sstevel@tonic-gate case '\n': 1137c478bd9Sstevel@tonic-gate if (l != 0) 1147c478bd9Sstevel@tonic-gate continue; 1157c478bd9Sstevel@tonic-gate asyn3(p1, p); 1167c478bd9Sstevel@tonic-gate asyntax(p->next, p2); 1177c478bd9Sstevel@tonic-gate return; 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate if (l == 0) 1207c478bd9Sstevel@tonic-gate asyn3(p1, p2); 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate 1236c02b4a4Smuffin void 1246c02b4a4Smuffin asyn3(struct wordent *p1, struct wordent *p2) 1257c478bd9Sstevel@tonic-gate { 1266c02b4a4Smuffin struct varent *ap; 1277c478bd9Sstevel@tonic-gate struct wordent alout; 1286c02b4a4Smuffin bool redid; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate #ifdef TRACE 1317c478bd9Sstevel@tonic-gate tprintf("TRACE- asyn3()\n"); 1327c478bd9Sstevel@tonic-gate #endif 1337c478bd9Sstevel@tonic-gate if (p1 == p2) 1347c478bd9Sstevel@tonic-gate return; 1357c478bd9Sstevel@tonic-gate if (p1->word[0] == '(') { 1367c478bd9Sstevel@tonic-gate for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 1377c478bd9Sstevel@tonic-gate if (p2 == p1) 1387c478bd9Sstevel@tonic-gate return; 1397c478bd9Sstevel@tonic-gate if (p2 == p1->next) 1407c478bd9Sstevel@tonic-gate return; 1417c478bd9Sstevel@tonic-gate asyn0(p1->next, p2); 1427c478bd9Sstevel@tonic-gate return; 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate ap = adrof1(p1->word, &aliases); 1457c478bd9Sstevel@tonic-gate if (ap == 0) 1467c478bd9Sstevel@tonic-gate return; 1477c478bd9Sstevel@tonic-gate alhistp = p1->prev; 1487c478bd9Sstevel@tonic-gate alhistt = p2; 1497c478bd9Sstevel@tonic-gate alvec = ap->vec; 1507c478bd9Sstevel@tonic-gate redid = lex(&alout); 1517c478bd9Sstevel@tonic-gate alhistp = alhistt = 0; 1527c478bd9Sstevel@tonic-gate alvec = 0; 1537c478bd9Sstevel@tonic-gate if (err) { 1547c478bd9Sstevel@tonic-gate freelex(&alout); 1557c478bd9Sstevel@tonic-gate error("%s", gettext(err)); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate if (p1->word[0] && eq(p1->word, alout.next->word)) { 1587c478bd9Sstevel@tonic-gate tchar *cp = alout.next->word; 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate alout.next->word = strspl(S_TOPBIT /* "\200" */, cp); 161*65b0c20eSnakanon xfree(cp); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate p1 = freenod(p1, redid ? p2 : p1->next); 1647c478bd9Sstevel@tonic-gate if (alout.next != &alout) { 1657c478bd9Sstevel@tonic-gate p1->next->prev = alout.prev->prev; 1667c478bd9Sstevel@tonic-gate alout.prev->prev->next = p1->next; 1677c478bd9Sstevel@tonic-gate alout.next->prev = p1; 1687c478bd9Sstevel@tonic-gate p1->next = alout.next; 169*65b0c20eSnakanon xfree(alout.prev->word); 170*65b0c20eSnakanon xfree(alout.prev); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate reset(); /* throw! */ 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate struct wordent * 1766c02b4a4Smuffin freenod(struct wordent *p1, struct wordent *p2) 1777c478bd9Sstevel@tonic-gate { 1786c02b4a4Smuffin struct wordent *retp = p1->prev; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate #ifdef TRACE 1817c478bd9Sstevel@tonic-gate tprintf("TRACE- freenod()\n"); 1827c478bd9Sstevel@tonic-gate #endif 1837c478bd9Sstevel@tonic-gate while (p1 != p2) { 184*65b0c20eSnakanon xfree(p1->word); 1857c478bd9Sstevel@tonic-gate p1 = p1->next; 186*65b0c20eSnakanon xfree(p1->prev); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate retp->next = p2; 1897c478bd9Sstevel@tonic-gate p2->prev = retp; 1907c478bd9Sstevel@tonic-gate return (retp); 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate #define PHERE 1 1947c478bd9Sstevel@tonic-gate #define PIN 2 1957c478bd9Sstevel@tonic-gate #define POUT 4 1967c478bd9Sstevel@tonic-gate #define PDIAG 8 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate /* 1997c478bd9Sstevel@tonic-gate * syntax 2007c478bd9Sstevel@tonic-gate * empty 2017c478bd9Sstevel@tonic-gate * syn0 2027c478bd9Sstevel@tonic-gate */ 2037c478bd9Sstevel@tonic-gate struct command * 2046c02b4a4Smuffin syntax(struct wordent *p1, struct wordent *p2, int flags) 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate #ifdef TRACE 2077c478bd9Sstevel@tonic-gate tprintf("TRACE- syntax()\n"); 2087c478bd9Sstevel@tonic-gate #endif 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate while (p1 != p2) 2117c478bd9Sstevel@tonic-gate /* if (any(p1->word[0], ";&\n")) */ /* for char -> tchar */ 2127c478bd9Sstevel@tonic-gate if (p1->word[0] == ';' || 2137c478bd9Sstevel@tonic-gate p1->word[0] == '&' || 2147c478bd9Sstevel@tonic-gate p1->word[0] == '\n') 2157c478bd9Sstevel@tonic-gate p1 = p1->next; 2167c478bd9Sstevel@tonic-gate else 2177c478bd9Sstevel@tonic-gate return (syn0(p1, p2, flags)); 2187c478bd9Sstevel@tonic-gate return (0); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate /* 2227c478bd9Sstevel@tonic-gate * syn0 2237c478bd9Sstevel@tonic-gate * syn1 2247c478bd9Sstevel@tonic-gate * syn1 & syntax 2257c478bd9Sstevel@tonic-gate */ 2267c478bd9Sstevel@tonic-gate struct command * 2276c02b4a4Smuffin syn0(struct wordent *p1, struct wordent *p2, int flags) 2287c478bd9Sstevel@tonic-gate { 2296c02b4a4Smuffin struct wordent *p; 2306c02b4a4Smuffin struct command *t, *t1; 2317c478bd9Sstevel@tonic-gate int l; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate #ifdef TRACE 2347c478bd9Sstevel@tonic-gate tprintf("TRACE- syn0()\n"); 2357c478bd9Sstevel@tonic-gate #endif 2367c478bd9Sstevel@tonic-gate l = 0; 2377c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 2387c478bd9Sstevel@tonic-gate switch (p->word[0]) { 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate case '(': 2417c478bd9Sstevel@tonic-gate l++; 2427c478bd9Sstevel@tonic-gate continue; 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate case ')': 2457c478bd9Sstevel@tonic-gate l--; 2467c478bd9Sstevel@tonic-gate if (l < 0) 2477c478bd9Sstevel@tonic-gate seterr("Too many )'s"); 2487c478bd9Sstevel@tonic-gate continue; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate case '|': 2517c478bd9Sstevel@tonic-gate if (p->word[1] == '|') 2527c478bd9Sstevel@tonic-gate continue; 2537c478bd9Sstevel@tonic-gate /* fall into ... */ 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate case '>': 2567c478bd9Sstevel@tonic-gate if (p->next != p2 && eq(p->next->word, S_AND /* "&" */)) 2577c478bd9Sstevel@tonic-gate p = p->next; 2587c478bd9Sstevel@tonic-gate continue; 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate case '&': 2617c478bd9Sstevel@tonic-gate if (l != 0) 2627c478bd9Sstevel@tonic-gate break; 2637c478bd9Sstevel@tonic-gate if (p->word[1] == '&') 2647c478bd9Sstevel@tonic-gate continue; 2657c478bd9Sstevel@tonic-gate t1 = syn1(p1, p, flags); 2667c478bd9Sstevel@tonic-gate if (t1->t_dtyp == TLST || 2677c478bd9Sstevel@tonic-gate t1->t_dtyp == TAND || 2687c478bd9Sstevel@tonic-gate t1->t_dtyp == TOR) { 269*65b0c20eSnakanon t = (struct command *)xcalloc(1, sizeof (*t)); 2707c478bd9Sstevel@tonic-gate t->t_dtyp = TPAR; 2717c478bd9Sstevel@tonic-gate t->t_dflg = FAND|FINT; 2727c478bd9Sstevel@tonic-gate t->t_dspr = t1; 2737c478bd9Sstevel@tonic-gate t1 = t; 2747c478bd9Sstevel@tonic-gate } else 2757c478bd9Sstevel@tonic-gate t1->t_dflg |= FAND|FINT; 276*65b0c20eSnakanon t = (struct command *)xcalloc(1, sizeof (*t)); 2777c478bd9Sstevel@tonic-gate t->t_dtyp = TLST; 2787c478bd9Sstevel@tonic-gate t->t_dflg = 0; 2797c478bd9Sstevel@tonic-gate t->t_dcar = t1; 2807c478bd9Sstevel@tonic-gate t->t_dcdr = syntax(p, p2, flags); 2817c478bd9Sstevel@tonic-gate return (t); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate if (l == 0) 2847c478bd9Sstevel@tonic-gate return (syn1(p1, p2, flags)); 2857c478bd9Sstevel@tonic-gate seterr("Too many ('s"); 2867c478bd9Sstevel@tonic-gate return (0); 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * syn1 2917c478bd9Sstevel@tonic-gate * syn1a 2927c478bd9Sstevel@tonic-gate * syn1a ; syntax 2937c478bd9Sstevel@tonic-gate */ 2947c478bd9Sstevel@tonic-gate struct command * 2956c02b4a4Smuffin syn1(struct wordent *p1, struct wordent *p2, int flags) 2967c478bd9Sstevel@tonic-gate { 2976c02b4a4Smuffin struct wordent *p; 2986c02b4a4Smuffin struct command *t; 2997c478bd9Sstevel@tonic-gate int l; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate #ifdef TRACE 3027c478bd9Sstevel@tonic-gate tprintf("TRACE- syn1()\n"); 3037c478bd9Sstevel@tonic-gate #endif 3047c478bd9Sstevel@tonic-gate l = 0; 3057c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 3067c478bd9Sstevel@tonic-gate switch (p->word[0]) { 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate case '(': 3097c478bd9Sstevel@tonic-gate l++; 3107c478bd9Sstevel@tonic-gate continue; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate case ')': 3137c478bd9Sstevel@tonic-gate l--; 3147c478bd9Sstevel@tonic-gate continue; 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate case ';': 3177c478bd9Sstevel@tonic-gate case '\n': 3187c478bd9Sstevel@tonic-gate if (l != 0) 3197c478bd9Sstevel@tonic-gate break; 320*65b0c20eSnakanon t = (struct command *)xcalloc(1, sizeof (*t)); 3217c478bd9Sstevel@tonic-gate t->t_dtyp = TLST; 3227c478bd9Sstevel@tonic-gate t->t_dcar = syn1a(p1, p, flags); 3237c478bd9Sstevel@tonic-gate t->t_dcdr = syntax(p->next, p2, flags); 3247c478bd9Sstevel@tonic-gate if (t->t_dcdr == 0) 3257c478bd9Sstevel@tonic-gate t->t_dcdr = t->t_dcar, t->t_dcar = 0; 3267c478bd9Sstevel@tonic-gate return (t); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate return (syn1a(p1, p2, flags)); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate /* 3327c478bd9Sstevel@tonic-gate * syn1a 3337c478bd9Sstevel@tonic-gate * syn1b 3347c478bd9Sstevel@tonic-gate * syn1b || syn1a 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate struct command * 3376c02b4a4Smuffin syn1a(struct wordent *p1, struct wordent *p2, int flags) 3387c478bd9Sstevel@tonic-gate { 3396c02b4a4Smuffin struct wordent *p; 3406c02b4a4Smuffin struct command *t; 3416c02b4a4Smuffin int l = 0; 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate #ifdef TRACE 3447c478bd9Sstevel@tonic-gate tprintf("TRACE- syn1a()\n"); 3457c478bd9Sstevel@tonic-gate #endif 3467c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 3477c478bd9Sstevel@tonic-gate switch (p->word[0]) { 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate case '(': 3507c478bd9Sstevel@tonic-gate l++; 3517c478bd9Sstevel@tonic-gate continue; 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate case ')': 3547c478bd9Sstevel@tonic-gate l--; 3557c478bd9Sstevel@tonic-gate continue; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate case '|': 3587c478bd9Sstevel@tonic-gate if (p->word[1] != '|') 3597c478bd9Sstevel@tonic-gate continue; 3607c478bd9Sstevel@tonic-gate if (l == 0) { 361*65b0c20eSnakanon t = (struct command *)xcalloc(1, sizeof (*t)); 3627c478bd9Sstevel@tonic-gate t->t_dtyp = TOR; 3637c478bd9Sstevel@tonic-gate t->t_dcar = syn1b(p1, p, flags); 3647c478bd9Sstevel@tonic-gate t->t_dcdr = syn1a(p->next, p2, flags); 3657c478bd9Sstevel@tonic-gate t->t_dflg = 0; 3667c478bd9Sstevel@tonic-gate return (t); 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate continue; 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate return (syn1b(p1, p2, flags)); 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate /* 3747c478bd9Sstevel@tonic-gate * syn1b 3757c478bd9Sstevel@tonic-gate * syn2 3767c478bd9Sstevel@tonic-gate * syn2 && syn1b 3777c478bd9Sstevel@tonic-gate */ 3787c478bd9Sstevel@tonic-gate struct command * 3796c02b4a4Smuffin syn1b(struct wordent *p1, struct wordent *p2, int flags) 3807c478bd9Sstevel@tonic-gate { 3816c02b4a4Smuffin struct wordent *p; 3826c02b4a4Smuffin struct command *t; 3836c02b4a4Smuffin int l = 0; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate #ifdef TRACE 3867c478bd9Sstevel@tonic-gate tprintf("TRACE- syn1b()\n"); 3877c478bd9Sstevel@tonic-gate #endif 3887c478bd9Sstevel@tonic-gate l = 0; 3897c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 3907c478bd9Sstevel@tonic-gate switch (p->word[0]) { 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate case '(': 3937c478bd9Sstevel@tonic-gate l++; 3947c478bd9Sstevel@tonic-gate continue; 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate case ')': 3977c478bd9Sstevel@tonic-gate l--; 3987c478bd9Sstevel@tonic-gate continue; 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate case '&': 4017c478bd9Sstevel@tonic-gate if (p->word[1] == '&' && l == 0) { 402*65b0c20eSnakanon t = (struct command *)xcalloc(1, sizeof (*t)); 4037c478bd9Sstevel@tonic-gate t->t_dtyp = TAND; 4047c478bd9Sstevel@tonic-gate t->t_dcar = syn2(p1, p, flags); 4057c478bd9Sstevel@tonic-gate t->t_dcdr = syn1b(p->next, p2, flags); 4067c478bd9Sstevel@tonic-gate t->t_dflg = 0; 4077c478bd9Sstevel@tonic-gate return (t); 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate continue; 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate return (syn2(p1, p2, flags)); 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate /* 4157c478bd9Sstevel@tonic-gate * syn2 4167c478bd9Sstevel@tonic-gate * syn3 4177c478bd9Sstevel@tonic-gate * syn3 | syn2 4187c478bd9Sstevel@tonic-gate * syn3 |& syn2 4197c478bd9Sstevel@tonic-gate */ 4207c478bd9Sstevel@tonic-gate struct command * 4216c02b4a4Smuffin syn2(struct wordent *p1, struct wordent *p2, int flags) 4227c478bd9Sstevel@tonic-gate { 4236c02b4a4Smuffin struct wordent *p, *pn; 4246c02b4a4Smuffin struct command *t; 4256c02b4a4Smuffin int l = 0; 4267c478bd9Sstevel@tonic-gate int f; 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate #ifdef TRACE 4297c478bd9Sstevel@tonic-gate tprintf("TRACE- syn2()\n"); 4307c478bd9Sstevel@tonic-gate #endif 4317c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 4327c478bd9Sstevel@tonic-gate switch (p->word[0]) { 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate case '(': 4357c478bd9Sstevel@tonic-gate l++; 4367c478bd9Sstevel@tonic-gate continue; 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate case ')': 4397c478bd9Sstevel@tonic-gate l--; 4407c478bd9Sstevel@tonic-gate continue; 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate case '|': 4437c478bd9Sstevel@tonic-gate if (l != 0) 4447c478bd9Sstevel@tonic-gate continue; 445*65b0c20eSnakanon t = (struct command *)xcalloc(1, sizeof (*t)); 4467c478bd9Sstevel@tonic-gate f = flags | POUT; 4477c478bd9Sstevel@tonic-gate pn = p->next; 4487c478bd9Sstevel@tonic-gate if (pn != p2 && pn->word[0] == '&') { 4497c478bd9Sstevel@tonic-gate f |= PDIAG; 4507c478bd9Sstevel@tonic-gate t->t_dflg |= FDIAG; 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate t->t_dtyp = TFIL; 4537c478bd9Sstevel@tonic-gate t->t_dcar = syn3(p1, p, f); 4547c478bd9Sstevel@tonic-gate if (pn != p2 && pn->word[0] == '&') 4557c478bd9Sstevel@tonic-gate p = pn; 4567c478bd9Sstevel@tonic-gate t->t_dcdr = syn2(p->next, p2, flags | PIN); 4577c478bd9Sstevel@tonic-gate return (t); 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate return (syn3(p1, p2, flags)); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate tchar RELPAR[] = {'<', '>', '(', ')', 0}; /* "<>()" */ 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate /* 4657c478bd9Sstevel@tonic-gate * syn3 4667c478bd9Sstevel@tonic-gate * ( syn0 ) [ < in ] [ > out ] 4677c478bd9Sstevel@tonic-gate * word word* [ < in ] [ > out ] 4687c478bd9Sstevel@tonic-gate * KEYWORD ( word* ) word* [ < in ] [ > out ] 4697c478bd9Sstevel@tonic-gate * 4707c478bd9Sstevel@tonic-gate * KEYWORD = (@ exit foreach if set switch test while) 4717c478bd9Sstevel@tonic-gate */ 4727c478bd9Sstevel@tonic-gate struct command * 4736c02b4a4Smuffin syn3(struct wordent *p1, struct wordent *p2, int flags) 4747c478bd9Sstevel@tonic-gate { 4756c02b4a4Smuffin struct wordent *p; 4767c478bd9Sstevel@tonic-gate struct wordent *lp, *rp; 4776c02b4a4Smuffin struct command *t; 4786c02b4a4Smuffin int l; 4797c478bd9Sstevel@tonic-gate tchar **av; 4807c478bd9Sstevel@tonic-gate int n, c; 4817c478bd9Sstevel@tonic-gate bool specp = 0; 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate #ifdef TRACE 4847c478bd9Sstevel@tonic-gate tprintf("TRACE- syn3()\n"); 4857c478bd9Sstevel@tonic-gate #endif 4867c478bd9Sstevel@tonic-gate if (p1 != p2) { 4877c478bd9Sstevel@tonic-gate p = p1; 4887c478bd9Sstevel@tonic-gate again: 4897c478bd9Sstevel@tonic-gate switch (srchx(p->word)) { 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate case ZELSE: 4927c478bd9Sstevel@tonic-gate p = p->next; 4937c478bd9Sstevel@tonic-gate if (p != p2) 4947c478bd9Sstevel@tonic-gate goto again; 4957c478bd9Sstevel@tonic-gate break; 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate case ZEXIT: 4987c478bd9Sstevel@tonic-gate case ZFOREACH: 4997c478bd9Sstevel@tonic-gate case ZIF: 5007c478bd9Sstevel@tonic-gate case ZLET: 5017c478bd9Sstevel@tonic-gate case ZSET: 5027c478bd9Sstevel@tonic-gate case ZSWITCH: 5037c478bd9Sstevel@tonic-gate case ZWHILE: 5047c478bd9Sstevel@tonic-gate specp = 1; 5057c478bd9Sstevel@tonic-gate break; 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate n = 0; 5097c478bd9Sstevel@tonic-gate l = 0; 5107c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 5117c478bd9Sstevel@tonic-gate switch (p->word[0]) { 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate case '(': 5147c478bd9Sstevel@tonic-gate if (specp) 5157c478bd9Sstevel@tonic-gate n++; 5167c478bd9Sstevel@tonic-gate l++; 5177c478bd9Sstevel@tonic-gate continue; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate case ')': 5207c478bd9Sstevel@tonic-gate if (specp) 5217c478bd9Sstevel@tonic-gate n++; 5227c478bd9Sstevel@tonic-gate l--; 5237c478bd9Sstevel@tonic-gate continue; 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate case '>': 5267c478bd9Sstevel@tonic-gate case '<': 5277c478bd9Sstevel@tonic-gate if (l != 0) { 5287c478bd9Sstevel@tonic-gate if (specp) 5297c478bd9Sstevel@tonic-gate n++; 5307c478bd9Sstevel@tonic-gate continue; 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate if (p->next == p2) 5337c478bd9Sstevel@tonic-gate continue; 5347c478bd9Sstevel@tonic-gate if (any(p->next->word[0], RELPAR)) 5357c478bd9Sstevel@tonic-gate continue; 5367c478bd9Sstevel@tonic-gate n--; 5377c478bd9Sstevel@tonic-gate continue; 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate default: 5407c478bd9Sstevel@tonic-gate if (!specp && l != 0) 5417c478bd9Sstevel@tonic-gate continue; 5427c478bd9Sstevel@tonic-gate n++; 5437c478bd9Sstevel@tonic-gate continue; 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate if (n < 0) 5467c478bd9Sstevel@tonic-gate n = 0; 547*65b0c20eSnakanon t = (struct command *)xcalloc(1, sizeof (*t)); 548*65b0c20eSnakanon av = (tchar **)xcalloc((unsigned)(n + 1), sizeof (tchar **)); 5497c478bd9Sstevel@tonic-gate t->t_dcom = av; 5507c478bd9Sstevel@tonic-gate n = 0; 5517c478bd9Sstevel@tonic-gate if (p2->word[0] == ')') 5527c478bd9Sstevel@tonic-gate t->t_dflg = FPAR; 5537c478bd9Sstevel@tonic-gate lp = 0; 5547c478bd9Sstevel@tonic-gate rp = 0; 5557c478bd9Sstevel@tonic-gate l = 0; 5567c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) { 5577c478bd9Sstevel@tonic-gate c = p->word[0]; 5587c478bd9Sstevel@tonic-gate switch (c) { 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate case '(': 5617c478bd9Sstevel@tonic-gate if (l == 0) { 5627c478bd9Sstevel@tonic-gate if (lp != 0 && !specp) 5637c478bd9Sstevel@tonic-gate seterr("Badly placed ("); 5647c478bd9Sstevel@tonic-gate lp = p->next; 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate l++; 5677c478bd9Sstevel@tonic-gate goto savep; 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate case ')': 5707c478bd9Sstevel@tonic-gate l--; 5717c478bd9Sstevel@tonic-gate if (l == 0) 5727c478bd9Sstevel@tonic-gate rp = p; 5737c478bd9Sstevel@tonic-gate goto savep; 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate case '>': 5767c478bd9Sstevel@tonic-gate if (l != 0) 5777c478bd9Sstevel@tonic-gate goto savep; 5787c478bd9Sstevel@tonic-gate if (p->word[1] == '>') 5797c478bd9Sstevel@tonic-gate t->t_dflg |= FCAT; 5807c478bd9Sstevel@tonic-gate if (p->next != p2 && eq(p->next->word, S_AND /* "&" */)) { 5817c478bd9Sstevel@tonic-gate t->t_dflg |= FDIAG, p = p->next; 5827c478bd9Sstevel@tonic-gate if (flags & (POUT|PDIAG)) 5837c478bd9Sstevel@tonic-gate goto badout; 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate if (p->next != p2 && eq(p->next->word, S_EXAS /* "!" */)) 5867c478bd9Sstevel@tonic-gate t->t_dflg |= FANY, p = p->next; 5877c478bd9Sstevel@tonic-gate if (p->next == p2) { 5887c478bd9Sstevel@tonic-gate missfile: 5897c478bd9Sstevel@tonic-gate seterr("Missing name for redirect"); 5907c478bd9Sstevel@tonic-gate continue; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate p = p->next; 5937c478bd9Sstevel@tonic-gate if (any(p->word[0], RELPAR)) 5947c478bd9Sstevel@tonic-gate goto missfile; 5957c478bd9Sstevel@tonic-gate if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit) 5967c478bd9Sstevel@tonic-gate badout: 5977c478bd9Sstevel@tonic-gate seterr("Ambiguous output redirect"); 5987c478bd9Sstevel@tonic-gate else 5997c478bd9Sstevel@tonic-gate t->t_drit = savestr(p->word); 6007c478bd9Sstevel@tonic-gate continue; 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate case '<': 6037c478bd9Sstevel@tonic-gate if (l != 0) 6047c478bd9Sstevel@tonic-gate goto savep; 6057c478bd9Sstevel@tonic-gate if (p->word[1] == '<') 6067c478bd9Sstevel@tonic-gate t->t_dflg |= FHERE; 6077c478bd9Sstevel@tonic-gate if (p->next == p2) 6087c478bd9Sstevel@tonic-gate goto missfile; 6097c478bd9Sstevel@tonic-gate p = p->next; 6107c478bd9Sstevel@tonic-gate if (any(p->word[0], RELPAR)) 6117c478bd9Sstevel@tonic-gate goto missfile; 6127c478bd9Sstevel@tonic-gate if ((flags & PHERE) && (t->t_dflg & FHERE)) 6137c478bd9Sstevel@tonic-gate seterr("Can't << within ()'s"); 6147c478bd9Sstevel@tonic-gate else if ((flags & PIN) || t->t_dlef) 6157c478bd9Sstevel@tonic-gate seterr("Ambiguous input redirect"); 6167c478bd9Sstevel@tonic-gate else 6177c478bd9Sstevel@tonic-gate t->t_dlef = savestr(p->word); 6187c478bd9Sstevel@tonic-gate continue; 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate savep: 6217c478bd9Sstevel@tonic-gate if (!specp) 6227c478bd9Sstevel@tonic-gate continue; 6237c478bd9Sstevel@tonic-gate default: 6247c478bd9Sstevel@tonic-gate if (l != 0 && !specp) 6257c478bd9Sstevel@tonic-gate continue; 6267c478bd9Sstevel@tonic-gate if (err == 0) 6277c478bd9Sstevel@tonic-gate av[n] = savestr(p->word); 6287c478bd9Sstevel@tonic-gate n++; 6297c478bd9Sstevel@tonic-gate continue; 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate if (lp != 0 && !specp) { 6337c478bd9Sstevel@tonic-gate if (n != 0) 6347c478bd9Sstevel@tonic-gate seterr("Badly placed ()'s"); 6357c478bd9Sstevel@tonic-gate t->t_dtyp = TPAR; 6367c478bd9Sstevel@tonic-gate t->t_dspr = syn0(lp, rp, PHERE); 6377c478bd9Sstevel@tonic-gate } else { 6387c478bd9Sstevel@tonic-gate if (n == 0) 6397c478bd9Sstevel@tonic-gate seterr("Invalid null command"); 6407c478bd9Sstevel@tonic-gate t->t_dtyp = TCOM; 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate return (t); 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate 6456c02b4a4Smuffin void 6466c02b4a4Smuffin freesyn(struct command *t) 6477c478bd9Sstevel@tonic-gate { 6487c478bd9Sstevel@tonic-gate #ifdef TRACE 6497c478bd9Sstevel@tonic-gate tprintf("TRACE- freesyn()\n"); 6507c478bd9Sstevel@tonic-gate #endif 6517c478bd9Sstevel@tonic-gate if (t == 0) 6527c478bd9Sstevel@tonic-gate return; 6537c478bd9Sstevel@tonic-gate switch (t->t_dtyp) { 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate case TCOM: 6567c478bd9Sstevel@tonic-gate blkfree(t->t_dcom); 6577c478bd9Sstevel@tonic-gate if (t->cfname) 6587c478bd9Sstevel@tonic-gate xfree(t->cfname); 6597c478bd9Sstevel@tonic-gate if (t->cargs) 6607c478bd9Sstevel@tonic-gate chr_blkfree(t->cargs); 6617c478bd9Sstevel@tonic-gate goto lr; 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate case TPAR: 6647c478bd9Sstevel@tonic-gate freesyn(t->t_dspr); 6657c478bd9Sstevel@tonic-gate /* fall into ... */ 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate lr: 668*65b0c20eSnakanon xfree(t->t_dlef); 669*65b0c20eSnakanon xfree(t->t_drit); 6707c478bd9Sstevel@tonic-gate break; 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate case TAND: 6737c478bd9Sstevel@tonic-gate case TOR: 6747c478bd9Sstevel@tonic-gate case TFIL: 6757c478bd9Sstevel@tonic-gate case TLST: 6767c478bd9Sstevel@tonic-gate freesyn(t->t_dcar), freesyn(t->t_dcdr); 6777c478bd9Sstevel@tonic-gate break; 6787c478bd9Sstevel@tonic-gate } 679*65b0c20eSnakanon xfree(t); 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate 6836c02b4a4Smuffin void 6846c02b4a4Smuffin chr_blkfree(char **vec) 6857c478bd9Sstevel@tonic-gate { 6866c02b4a4Smuffin char **av; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate for (av = vec; *av; av++) 6897c478bd9Sstevel@tonic-gate xfree(*av); 6907c478bd9Sstevel@tonic-gate xfree(vec); 6917c478bd9Sstevel@tonic-gate } 692