1*17511Sedward #ifndef lint 2*17511Sedward static char *sccsid = "@(#)parse.c 4.2 (Berkeley) 12/13/84"; 3*17511Sedward #endif 41301Sbill 51301Sbill #include "sh.h" 61301Sbill 71301Sbill /* 81301Sbill * C shell 91301Sbill */ 101301Sbill 111301Sbill /* 121301Sbill * Perform aliasing on the word list lex 131301Sbill * Do a (very rudimentary) parse to separate into commands. 141301Sbill * If word 0 of a command has an alias, do it. 151301Sbill * Repeat a maximum of 20 times. 161301Sbill */ 171301Sbill alias(lex) 181301Sbill register struct wordent *lex; 191301Sbill { 201301Sbill int aleft = 21; 211301Sbill jmp_buf osetexit; 221301Sbill 231301Sbill getexit(osetexit); 241301Sbill setexit(); 251301Sbill if (haderr) { 261301Sbill resexit(osetexit); 271301Sbill reset(); 281301Sbill } 291301Sbill if (--aleft == 0) 301301Sbill error("Alias loop"); 311301Sbill asyntax(lex->next, lex); 321301Sbill resexit(osetexit); 331301Sbill } 341301Sbill 351301Sbill asyntax(p1, p2) 361301Sbill register struct wordent *p1, *p2; 371301Sbill { 381301Sbill 391301Sbill while (p1 != p2) 401301Sbill if (any(p1->word[0], ";&\n")) 411301Sbill p1 = p1->next; 421301Sbill else { 431301Sbill asyn0(p1, p2); 441301Sbill return; 451301Sbill } 461301Sbill } 471301Sbill 481301Sbill asyn0(p1, p2) 491301Sbill struct wordent *p1; 501301Sbill register struct wordent *p2; 511301Sbill { 521301Sbill register struct wordent *p; 531301Sbill register int l = 0; 541301Sbill 551301Sbill for (p = p1; p != p2; p = p->next) 561301Sbill switch (p->word[0]) { 571301Sbill 581301Sbill case '(': 591301Sbill l++; 601301Sbill continue; 611301Sbill 621301Sbill case ')': 631301Sbill l--; 641301Sbill if (l < 0) 651301Sbill error("Too many )'s"); 661301Sbill continue; 671301Sbill 681301Sbill case '>': 691301Sbill if (p->next != p2 && eq(p->next->word, "&")) 701301Sbill p = p->next; 711301Sbill continue; 721301Sbill 731301Sbill case '&': 741301Sbill case '|': 751301Sbill case ';': 761301Sbill case '\n': 771301Sbill if (l != 0) 781301Sbill continue; 791301Sbill asyn3(p1, p); 801301Sbill asyntax(p->next, p2); 811301Sbill return; 821301Sbill } 831301Sbill if (l == 0) 841301Sbill asyn3(p1, p2); 851301Sbill } 861301Sbill 871301Sbill asyn3(p1, p2) 881301Sbill struct wordent *p1; 891301Sbill register struct wordent *p2; 901301Sbill { 911301Sbill register struct varent *ap; 921301Sbill struct wordent alout; 931301Sbill register bool redid; 941301Sbill 951301Sbill if (p1 == p2) 961301Sbill return; 971301Sbill if (p1->word[0] == '(') { 981301Sbill for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 991301Sbill if (p2 == p1) 1001301Sbill return; 1011301Sbill if (p2 == p1->next) 1021301Sbill return; 1031301Sbill asyn0(p1->next, p2); 1041301Sbill return; 1051301Sbill } 1061301Sbill ap = adrof1(p1->word, &aliases); 1071301Sbill if (ap == 0) 1081301Sbill return; 1091301Sbill alhistp = p1->prev; 1101301Sbill alhistt = p2; 1111301Sbill alvec = ap->vec; 1121301Sbill redid = lex(&alout); 1131301Sbill alhistp = alhistt = 0; 1141301Sbill alvec = 0; 1151301Sbill if (err) { 1161301Sbill freelex(&alout); 1171301Sbill error(err); 1181301Sbill } 1191301Sbill if (p1->word[0] && eq(p1->word, alout.next->word)) { 1201301Sbill char *cp = alout.next->word; 1211301Sbill 1221301Sbill alout.next->word = strspl("\200", cp); 123*17511Sedward XFREE(cp) 1241301Sbill } 1251301Sbill p1 = freenod(p1, redid ? p2 : p1->next); 1261301Sbill if (alout.next != &alout) { 1271301Sbill p1->next->prev = alout.prev->prev; 1281301Sbill alout.prev->prev->next = p1->next; 1291301Sbill alout.next->prev = p1; 1301301Sbill p1->next = alout.next; 131*17511Sedward XFREE(alout.prev->word) 132*17511Sedward XFREE((char *)alout.prev) 1331301Sbill } 1341301Sbill reset(); /* throw! */ 1351301Sbill } 1361301Sbill 1371301Sbill struct wordent * 1381301Sbill freenod(p1, p2) 1391301Sbill register struct wordent *p1, *p2; 1401301Sbill { 1411301Sbill register struct wordent *retp = p1->prev; 1421301Sbill 1431301Sbill while (p1 != p2) { 144*17511Sedward XFREE(p1->word) 1451301Sbill p1 = p1->next; 146*17511Sedward XFREE((char *)p1->prev) 1471301Sbill } 1481301Sbill retp->next = p2; 1491301Sbill p2->prev = retp; 1501301Sbill return (retp); 1511301Sbill } 1521301Sbill 1531301Sbill #define PHERE 1 1541301Sbill #define PIN 2 1551301Sbill #define POUT 4 1561301Sbill #define PDIAG 8 1571301Sbill 1581301Sbill /* 1591301Sbill * syntax 1601301Sbill * empty 1611301Sbill * syn0 1621301Sbill */ 1631301Sbill struct command * 1641301Sbill syntax(p1, p2, flags) 1651301Sbill register struct wordent *p1, *p2; 1661301Sbill int flags; 1671301Sbill { 1681301Sbill 1691301Sbill while (p1 != p2) 1701301Sbill if (any(p1->word[0], ";&\n")) 1711301Sbill p1 = p1->next; 1721301Sbill else 1731301Sbill return (syn0(p1, p2, flags)); 1741301Sbill return (0); 1751301Sbill } 1761301Sbill 1771301Sbill /* 1781301Sbill * syn0 1791301Sbill * syn1 1801301Sbill * syn1 & syntax 1811301Sbill */ 1821301Sbill struct command * 1831301Sbill syn0(p1, p2, flags) 1841301Sbill struct wordent *p1, *p2; 1851301Sbill int flags; 1861301Sbill { 1871301Sbill register struct wordent *p; 1881301Sbill register struct command *t, *t1; 1891301Sbill int l; 1901301Sbill 1911301Sbill l = 0; 1921301Sbill for (p = p1; p != p2; p = p->next) 1931301Sbill switch (p->word[0]) { 1941301Sbill 1951301Sbill case '(': 1961301Sbill l++; 1971301Sbill continue; 1981301Sbill 1991301Sbill case ')': 2001301Sbill l--; 2011301Sbill if (l < 0) 2021301Sbill seterr("Too many )'s"); 2031301Sbill continue; 2041301Sbill 2051301Sbill case '|': 2061301Sbill if (p->word[1] == '|') 2071301Sbill continue; 2081301Sbill /* fall into ... */ 2091301Sbill 2101301Sbill case '>': 2111301Sbill if (p->next != p2 && eq(p->next->word, "&")) 2121301Sbill p = p->next; 2131301Sbill continue; 2141301Sbill 2151301Sbill case '&': 2161301Sbill if (l != 0) 2171301Sbill break; 2181301Sbill if (p->word[1] == '&') 2191301Sbill continue; 2201301Sbill t1 = syn1(p1, p, flags); 2211301Sbill if (t1->t_dtyp == TLST) { 2221301Sbill t = (struct command *) calloc(1, sizeof (*t)); 2231301Sbill t->t_dtyp = TPAR; 2241301Sbill t->t_dflg = FAND|FINT; 2251301Sbill t->t_dspr = t1; 2261301Sbill t1 = t; 2271301Sbill } else 2281301Sbill t1->t_dflg |= FAND|FINT; 2291301Sbill t = (struct command *) calloc(1, sizeof (*t)); 2301301Sbill t->t_dtyp = TLST; 2311301Sbill t->t_dflg = 0; 2321301Sbill t->t_dcar = t1; 2331301Sbill t->t_dcdr = syntax(p, p2, flags); 2341301Sbill return(t); 2351301Sbill } 2361301Sbill if (l == 0) 2371301Sbill return (syn1(p1, p2, flags)); 2381301Sbill seterr("Too many ('s"); 2391301Sbill return (0); 2401301Sbill } 2411301Sbill 2421301Sbill /* 2431301Sbill * syn1 2441301Sbill * syn1a 2451301Sbill * syn1a ; syntax 2461301Sbill */ 2471301Sbill struct command * 2481301Sbill syn1(p1, p2, flags) 2491301Sbill struct wordent *p1, *p2; 2501301Sbill int flags; 2511301Sbill { 2521301Sbill register struct wordent *p; 2531301Sbill register struct command *t; 2541301Sbill int l; 2551301Sbill 2561301Sbill l = 0; 2571301Sbill for (p = p1; p != p2; p = p->next) 2581301Sbill switch (p->word[0]) { 2591301Sbill 2601301Sbill case '(': 2611301Sbill l++; 2621301Sbill continue; 2631301Sbill 2641301Sbill case ')': 2651301Sbill l--; 2661301Sbill continue; 2671301Sbill 2681301Sbill case ';': 2691301Sbill case '\n': 2701301Sbill if (l != 0) 2711301Sbill break; 2721301Sbill t = (struct command *) calloc(1, sizeof (*t)); 2731301Sbill t->t_dtyp = TLST; 2741301Sbill t->t_dcar = syn1a(p1, p, flags); 2751301Sbill t->t_dcdr = syntax(p->next, p2, flags); 2761301Sbill if (t->t_dcdr == 0) 2771301Sbill t->t_dcdr = t->t_dcar, t->t_dcar = 0; 2781301Sbill return (t); 2791301Sbill } 2801301Sbill return (syn1a(p1, p2, flags)); 2811301Sbill } 2821301Sbill 2831301Sbill /* 2841301Sbill * syn1a 2851301Sbill * syn1b 2861301Sbill * syn1b || syn1a 2871301Sbill */ 2881301Sbill struct command * 2891301Sbill syn1a(p1, p2, flags) 2901301Sbill struct wordent *p1, *p2; 2911301Sbill int flags; 2921301Sbill { 2931301Sbill register struct wordent *p; 2941301Sbill register struct command *t; 2951301Sbill register int l = 0; 2961301Sbill 2971301Sbill for (p = p1; p != p2; p = p->next) 2981301Sbill switch (p->word[0]) { 2991301Sbill 3001301Sbill case '(': 3011301Sbill l++; 3021301Sbill continue; 3031301Sbill 3041301Sbill case ')': 3051301Sbill l--; 3061301Sbill continue; 3071301Sbill 3081301Sbill case '|': 3091301Sbill if (p->word[1] != '|') 3101301Sbill continue; 3111301Sbill if (l == 0) { 3121301Sbill t = (struct command *) calloc(1, sizeof (*t)); 3131301Sbill t->t_dtyp = TOR; 3141301Sbill t->t_dcar = syn1b(p1, p, flags); 3151301Sbill t->t_dcdr = syn1a(p->next, p2, flags); 3161301Sbill t->t_dflg = 0; 3171301Sbill return (t); 3181301Sbill } 3191301Sbill continue; 3201301Sbill } 3211301Sbill return (syn1b(p1, p2, flags)); 3221301Sbill } 3231301Sbill 3241301Sbill /* 3251301Sbill * syn1b 3261301Sbill * syn2 3271301Sbill * syn2 && syn1b 3281301Sbill */ 3291301Sbill struct command * 3301301Sbill syn1b(p1, p2, flags) 3311301Sbill struct wordent *p1, *p2; 3321301Sbill int flags; 3331301Sbill { 3341301Sbill register struct wordent *p; 3351301Sbill register struct command *t; 3361301Sbill register int l = 0; 3371301Sbill 3381301Sbill l = 0; 3391301Sbill for (p = p1; p != p2; p = p->next) 3401301Sbill switch (p->word[0]) { 3411301Sbill 3421301Sbill case '(': 3431301Sbill l++; 3441301Sbill continue; 3451301Sbill 3461301Sbill case ')': 3471301Sbill l--; 3481301Sbill continue; 3491301Sbill 3501301Sbill case '&': 3511301Sbill if (p->word[1] == '&' && l == 0) { 3521301Sbill t = (struct command *) calloc(1, sizeof (*t)); 3531301Sbill t->t_dtyp = TAND; 3541301Sbill t->t_dcar = syn2(p1, p, flags); 3551301Sbill t->t_dcdr = syn1b(p->next, p2, flags); 3561301Sbill t->t_dflg = 0; 3571301Sbill return (t); 3581301Sbill } 3591301Sbill continue; 3601301Sbill } 3611301Sbill return (syn2(p1, p2, flags)); 3621301Sbill } 3631301Sbill 3641301Sbill /* 3651301Sbill * syn2 3661301Sbill * syn3 3671301Sbill * syn3 | syn2 3681301Sbill * syn3 |& syn2 3691301Sbill */ 3701301Sbill struct command * 3711301Sbill syn2(p1, p2, flags) 3721301Sbill struct wordent *p1, *p2; 3731301Sbill int flags; 3741301Sbill { 3751301Sbill register struct wordent *p, *pn; 3761301Sbill register struct command *t; 3771301Sbill register int l = 0; 3781301Sbill int f; 3791301Sbill 3801301Sbill for (p = p1; p != p2; p = p->next) 3811301Sbill switch (p->word[0]) { 3821301Sbill 3831301Sbill case '(': 3841301Sbill l++; 3851301Sbill continue; 3861301Sbill 3871301Sbill case ')': 3881301Sbill l--; 3891301Sbill continue; 3901301Sbill 3911301Sbill case '|': 3921301Sbill if (l != 0) 3931301Sbill continue; 3941301Sbill t = (struct command *) calloc(1, sizeof (*t)); 3951301Sbill f = flags | POUT; 3961301Sbill pn = p->next; 3971301Sbill if (pn != p2 && pn->word[0] == '&') { 3981301Sbill f |= PDIAG; 3991301Sbill t->t_dflg |= FDIAG; 4001301Sbill } 4011301Sbill t->t_dtyp = TFIL; 4021301Sbill t->t_dcar = syn3(p1, p, f); 4031301Sbill if (pn != p2 && pn->word[0] == '&') 4041301Sbill p = pn; 4051301Sbill t->t_dcdr = syn2(p->next, p2, flags | PIN); 4061301Sbill return (t); 4071301Sbill } 4081301Sbill return (syn3(p1, p2, flags)); 4091301Sbill } 4101301Sbill 4111301Sbill char *RELPAR = "<>()"; 4121301Sbill 4131301Sbill /* 4141301Sbill * syn3 4151301Sbill * ( syn0 ) [ < in ] [ > out ] 4161301Sbill * word word* [ < in ] [ > out ] 4171301Sbill * KEYWORD ( word* ) word* [ < in ] [ > out ] 4181301Sbill * 4191301Sbill * KEYWORD = (@ exit foreach if set switch test while) 4201301Sbill */ 4211301Sbill struct command * 4221301Sbill syn3(p1, p2, flags) 4231301Sbill struct wordent *p1, *p2; 4241301Sbill int flags; 4251301Sbill { 4261301Sbill register struct wordent *p; 4271301Sbill struct wordent *lp, *rp; 4281301Sbill register struct command *t; 4291301Sbill register int l; 4301301Sbill char **av; 4311301Sbill int n, c; 4321301Sbill bool specp = 0; 4331301Sbill 4341301Sbill if (p1 != p2) { 4351301Sbill p = p1; 4361301Sbill again: 4371301Sbill switch (srchx(p->word)) { 4381301Sbill 4391301Sbill case ZELSE: 4401301Sbill p = p->next; 4411301Sbill if (p != p2) 4421301Sbill goto again; 4431301Sbill break; 4441301Sbill 4451301Sbill case ZEXIT: 4461301Sbill case ZFOREACH: 4471301Sbill case ZIF: 4481301Sbill case ZLET: 4491301Sbill case ZSET: 4501301Sbill case ZSWITCH: 4511301Sbill case ZWHILE: 4521301Sbill specp = 1; 4531301Sbill break; 4541301Sbill } 4551301Sbill } 4561301Sbill n = 0; 4571301Sbill l = 0; 4581301Sbill for (p = p1; p != p2; p = p->next) 4591301Sbill switch (p->word[0]) { 4601301Sbill 4611301Sbill case '(': 4621301Sbill if (specp) 4631301Sbill n++; 4641301Sbill l++; 4651301Sbill continue; 4661301Sbill 4671301Sbill case ')': 4681301Sbill if (specp) 4691301Sbill n++; 4701301Sbill l--; 4711301Sbill continue; 4721301Sbill 4731301Sbill case '>': 4741301Sbill case '<': 4751301Sbill if (l != 0) { 4761301Sbill if (specp) 4771301Sbill n++; 4781301Sbill continue; 4791301Sbill } 4801301Sbill if (p->next == p2) 4811301Sbill continue; 4821301Sbill if (any(p->next->word[0], RELPAR)) 4831301Sbill continue; 4841301Sbill n--; 4851301Sbill continue; 4861301Sbill 4871301Sbill default: 4881301Sbill if (!specp && l != 0) 4891301Sbill continue; 4901301Sbill n++; 4911301Sbill continue; 4921301Sbill } 4931301Sbill if (n < 0) 4941301Sbill n = 0; 4951301Sbill t = (struct command *) calloc(1, sizeof (*t)); 496*17511Sedward av = (char **) calloc((unsigned) (n + 1), sizeof (char **)); 4971301Sbill t->t_dcom = av; 4981301Sbill n = 0; 4991301Sbill if (p2->word[0] == ')') 5001301Sbill t->t_dflg = FPAR; 5011301Sbill lp = 0; 5021301Sbill rp = 0; 5031301Sbill l = 0; 5041301Sbill for (p = p1; p != p2; p = p->next) { 5051301Sbill c = p->word[0]; 5061301Sbill switch (c) { 5071301Sbill 5081301Sbill case '(': 5091301Sbill if (l == 0) { 5101301Sbill if (lp != 0 && !specp) 5111301Sbill seterr("Badly placed ("); 5121301Sbill lp = p->next; 5131301Sbill } 5141301Sbill l++; 5151301Sbill goto savep; 5161301Sbill 5171301Sbill case ')': 5181301Sbill l--; 5191301Sbill if (l == 0) 5201301Sbill rp = p; 5211301Sbill goto savep; 5221301Sbill 5231301Sbill case '>': 5241301Sbill if (l != 0) 5251301Sbill goto savep; 5261301Sbill if (p->word[1] == '>') 5271301Sbill t->t_dflg |= FCAT; 5281301Sbill if (p->next != p2 && eq(p->next->word, "&")) { 5291301Sbill t->t_dflg |= FDIAG, p = p->next; 5301301Sbill if (flags & (POUT|PDIAG)) 5311301Sbill goto badout; 5321301Sbill } 5331301Sbill if (p->next != p2 && eq(p->next->word, "!")) 5341301Sbill t->t_dflg |= FANY, p = p->next; 5351301Sbill if (p->next == p2) { 5361301Sbill missfile: 5371301Sbill seterr("Missing name for redirect"); 5381301Sbill continue; 5391301Sbill } 5401301Sbill p = p->next; 5411301Sbill if (any(p->word[0], RELPAR)) 5421301Sbill goto missfile; 5431301Sbill if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit) 5441301Sbill badout: 5451301Sbill seterr("Ambiguous output redirect"); 5461301Sbill else 5471301Sbill t->t_drit = savestr(p->word); 5481301Sbill continue; 5491301Sbill 5501301Sbill case '<': 5511301Sbill if (l != 0) 5521301Sbill goto savep; 5531301Sbill if (p->word[1] == '<') 5541301Sbill t->t_dflg |= FHERE; 5551301Sbill if (p->next == p2) 5561301Sbill goto missfile; 5571301Sbill p = p->next; 5581301Sbill if (any(p->word[0], RELPAR)) 5591301Sbill goto missfile; 5601301Sbill if ((flags & PHERE) && (t->t_dflg & FHERE)) 5611301Sbill seterr("Can't << within ()'s"); 5621301Sbill else if ((flags & PIN) || t->t_dlef) 5631301Sbill seterr("Ambiguous input redirect"); 5641301Sbill else 5651301Sbill t->t_dlef = savestr(p->word); 5661301Sbill continue; 5671301Sbill 5681301Sbill savep: 5691301Sbill if (!specp) 5701301Sbill continue; 5711301Sbill default: 5721301Sbill if (l != 0 && !specp) 5731301Sbill continue; 5741301Sbill if (err == 0) 5751301Sbill av[n] = savestr(p->word); 5761301Sbill n++; 5771301Sbill continue; 5781301Sbill } 5791301Sbill } 5801301Sbill if (lp != 0 && !specp) { 5811301Sbill if (n != 0) 5821301Sbill seterr("Badly placed ()'s"); 5831301Sbill t->t_dtyp = TPAR; 5841301Sbill t->t_dspr = syn0(lp, rp, PHERE); 5851301Sbill } else { 5861301Sbill if (n == 0) 5871301Sbill seterr("Invalid null command"); 5881301Sbill t->t_dtyp = TCOM; 5891301Sbill } 5901301Sbill return (t); 5911301Sbill } 5921301Sbill 5931301Sbill freesyn(t) 5941301Sbill register struct command *t; 5951301Sbill { 5961301Sbill register char **v; 5971301Sbill 5981301Sbill if (t == 0) 5991301Sbill return; 6001301Sbill switch (t->t_dtyp) { 6011301Sbill 6021301Sbill case TCOM: 6031301Sbill for (v = t->t_dcom; *v; v++) 604*17511Sedward XFREE(*v) 605*17511Sedward XFREE((char *)t->t_dcom) 6061301Sbill goto lr; 6071301Sbill 6081301Sbill case TPAR: 6091301Sbill freesyn(t->t_dspr); 6101301Sbill /* fall into ... */ 6111301Sbill 6121301Sbill lr: 613*17511Sedward XFREE(t->t_dlef) 614*17511Sedward XFREE(t->t_drit) 6151301Sbill break; 6161301Sbill 6171301Sbill case TAND: 6181301Sbill case TOR: 6191301Sbill case TFIL: 6201301Sbill case TLST: 6211301Sbill freesyn(t->t_dcar), freesyn(t->t_dcdr); 6221301Sbill break; 6231301Sbill } 624*17511Sedward XFREE((char *)t) 6251301Sbill } 626