121939Sdist /* 221939Sdist * Copyright (c) 1980 Regents of the University of California. 322538Sedward * All rights reserved. The Berkeley Software License Agreement 421939Sdist * specifies the terms and conditions for redistribution. 521939Sdist */ 621939Sdist 717511Sedward #ifndef lint 8*47724Sbostic static char *sccsid = "@(#)parse.c 5.5 (Berkeley) 04/01/91"; 922538Sedward #endif 101301Sbill 111301Sbill #include "sh.h" 121301Sbill 131301Sbill /* 141301Sbill * C shell 151301Sbill */ 161301Sbill 171301Sbill /* 181301Sbill * Perform aliasing on the word list lex 191301Sbill * Do a (very rudimentary) parse to separate into commands. 201301Sbill * If word 0 of a command has an alias, do it. 211301Sbill * Repeat a maximum of 20 times. 221301Sbill */ 231301Sbill alias(lex) 241301Sbill register struct wordent *lex; 251301Sbill { 261301Sbill int aleft = 21; 271301Sbill jmp_buf osetexit; 281301Sbill 291301Sbill getexit(osetexit); 30*47724Sbostic (void)setjmp(reslab); 311301Sbill if (haderr) { 321301Sbill resexit(osetexit); 33*47724Sbostic longjmp(reslab, 0); 341301Sbill } 351301Sbill if (--aleft == 0) 361301Sbill error("Alias loop"); 371301Sbill asyntax(lex->next, lex); 381301Sbill resexit(osetexit); 391301Sbill } 401301Sbill 411301Sbill asyntax(p1, p2) 421301Sbill register struct wordent *p1, *p2; 431301Sbill { 441301Sbill 451301Sbill while (p1 != p2) 4647419Sbostic if (index(";&\n", p1->word[0])) 471301Sbill p1 = p1->next; 481301Sbill else { 491301Sbill asyn0(p1, p2); 501301Sbill return; 511301Sbill } 521301Sbill } 531301Sbill 541301Sbill asyn0(p1, p2) 551301Sbill struct wordent *p1; 561301Sbill register struct wordent *p2; 571301Sbill { 581301Sbill register struct wordent *p; 591301Sbill register int l = 0; 601301Sbill 611301Sbill for (p = p1; p != p2; p = p->next) 621301Sbill switch (p->word[0]) { 631301Sbill 641301Sbill case '(': 651301Sbill l++; 661301Sbill continue; 671301Sbill 681301Sbill case ')': 691301Sbill l--; 701301Sbill if (l < 0) 711301Sbill error("Too many )'s"); 721301Sbill continue; 731301Sbill 741301Sbill case '>': 751301Sbill if (p->next != p2 && eq(p->next->word, "&")) 761301Sbill p = p->next; 771301Sbill continue; 781301Sbill 791301Sbill case '&': 801301Sbill case '|': 811301Sbill case ';': 821301Sbill case '\n': 831301Sbill if (l != 0) 841301Sbill continue; 851301Sbill asyn3(p1, p); 861301Sbill asyntax(p->next, p2); 871301Sbill return; 881301Sbill } 891301Sbill if (l == 0) 901301Sbill asyn3(p1, p2); 911301Sbill } 921301Sbill 931301Sbill asyn3(p1, p2) 941301Sbill struct wordent *p1; 951301Sbill register struct wordent *p2; 961301Sbill { 971301Sbill register struct varent *ap; 981301Sbill struct wordent alout; 991301Sbill register bool redid; 1001301Sbill 1011301Sbill if (p1 == p2) 1021301Sbill return; 1031301Sbill if (p1->word[0] == '(') { 1041301Sbill for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 1051301Sbill if (p2 == p1) 1061301Sbill return; 1071301Sbill if (p2 == p1->next) 1081301Sbill return; 1091301Sbill asyn0(p1->next, p2); 1101301Sbill return; 1111301Sbill } 1121301Sbill ap = adrof1(p1->word, &aliases); 1131301Sbill if (ap == 0) 1141301Sbill return; 1151301Sbill alhistp = p1->prev; 1161301Sbill alhistt = p2; 1171301Sbill alvec = ap->vec; 1181301Sbill redid = lex(&alout); 1191301Sbill alhistp = alhistt = 0; 1201301Sbill alvec = 0; 1211301Sbill if (err) { 1221301Sbill freelex(&alout); 1231301Sbill error(err); 1241301Sbill } 1251301Sbill if (p1->word[0] && eq(p1->word, alout.next->word)) { 1261301Sbill char *cp = alout.next->word; 1271301Sbill 1281301Sbill alout.next->word = strspl("\200", cp); 12917511Sedward XFREE(cp) 1301301Sbill } 1311301Sbill p1 = freenod(p1, redid ? p2 : p1->next); 1321301Sbill if (alout.next != &alout) { 1331301Sbill p1->next->prev = alout.prev->prev; 1341301Sbill alout.prev->prev->next = p1->next; 1351301Sbill alout.next->prev = p1; 1361301Sbill p1->next = alout.next; 13717511Sedward XFREE(alout.prev->word) 13817511Sedward XFREE((char *)alout.prev) 1391301Sbill } 140*47724Sbostic longjmp(reslab, 0); /* throw! */ 1411301Sbill } 1421301Sbill 1431301Sbill struct wordent * 1441301Sbill freenod(p1, p2) 1451301Sbill register struct wordent *p1, *p2; 1461301Sbill { 1471301Sbill register struct wordent *retp = p1->prev; 1481301Sbill 1491301Sbill while (p1 != p2) { 15017511Sedward XFREE(p1->word) 1511301Sbill p1 = p1->next; 15217511Sedward XFREE((char *)p1->prev) 1531301Sbill } 1541301Sbill retp->next = p2; 1551301Sbill p2->prev = retp; 1561301Sbill return (retp); 1571301Sbill } 1581301Sbill 1591301Sbill #define PHERE 1 1601301Sbill #define PIN 2 1611301Sbill #define POUT 4 1621301Sbill #define PDIAG 8 1631301Sbill 1641301Sbill /* 1651301Sbill * syntax 1661301Sbill * empty 1671301Sbill * syn0 1681301Sbill */ 1691301Sbill struct command * 1701301Sbill syntax(p1, p2, flags) 1711301Sbill register struct wordent *p1, *p2; 1721301Sbill int flags; 1731301Sbill { 1741301Sbill 1751301Sbill while (p1 != p2) 17647419Sbostic if (index(";&\n", p1->word[0])) 1771301Sbill p1 = p1->next; 1781301Sbill else 1791301Sbill return (syn0(p1, p2, flags)); 1801301Sbill return (0); 1811301Sbill } 1821301Sbill 1831301Sbill /* 1841301Sbill * syn0 1851301Sbill * syn1 1861301Sbill * syn1 & syntax 1871301Sbill */ 1881301Sbill struct command * 1891301Sbill syn0(p1, p2, flags) 1901301Sbill struct wordent *p1, *p2; 1911301Sbill int flags; 1921301Sbill { 1931301Sbill register struct wordent *p; 1941301Sbill register struct command *t, *t1; 1951301Sbill int l; 1961301Sbill 1971301Sbill l = 0; 1981301Sbill for (p = p1; p != p2; p = p->next) 1991301Sbill switch (p->word[0]) { 2001301Sbill 2011301Sbill case '(': 2021301Sbill l++; 2031301Sbill continue; 2041301Sbill 2051301Sbill case ')': 2061301Sbill l--; 2071301Sbill if (l < 0) 2081301Sbill seterr("Too many )'s"); 2091301Sbill continue; 2101301Sbill 2111301Sbill case '|': 2121301Sbill if (p->word[1] == '|') 2131301Sbill continue; 2141301Sbill /* fall into ... */ 2151301Sbill 2161301Sbill case '>': 2171301Sbill if (p->next != p2 && eq(p->next->word, "&")) 2181301Sbill p = p->next; 2191301Sbill continue; 2201301Sbill 2211301Sbill case '&': 2221301Sbill if (l != 0) 2231301Sbill break; 2241301Sbill if (p->word[1] == '&') 2251301Sbill continue; 2261301Sbill t1 = syn1(p1, p, flags); 227*47724Sbostic if (t1->t_dtyp == NODE_LIST || 228*47724Sbostic t1->t_dtyp == NODE_AND || 229*47724Sbostic t1->t_dtyp == NODE_OR) { 2301301Sbill t = (struct command *) calloc(1, sizeof (*t)); 231*47724Sbostic t->t_dtyp = NODE_PAREN; 232*47724Sbostic t->t_dflg = F_AMPERSAND|F_NOINTERRUPT; 2331301Sbill t->t_dspr = t1; 2341301Sbill t1 = t; 2351301Sbill } else 236*47724Sbostic t1->t_dflg |= F_AMPERSAND|F_NOINTERRUPT; 2371301Sbill t = (struct command *) calloc(1, sizeof (*t)); 238*47724Sbostic t->t_dtyp = NODE_LIST; 2391301Sbill t->t_dflg = 0; 2401301Sbill t->t_dcar = t1; 2411301Sbill t->t_dcdr = syntax(p, p2, flags); 2421301Sbill return(t); 2431301Sbill } 2441301Sbill if (l == 0) 2451301Sbill return (syn1(p1, p2, flags)); 2461301Sbill seterr("Too many ('s"); 2471301Sbill return (0); 2481301Sbill } 2491301Sbill 2501301Sbill /* 2511301Sbill * syn1 2521301Sbill * syn1a 2531301Sbill * syn1a ; syntax 2541301Sbill */ 2551301Sbill struct command * 2561301Sbill syn1(p1, p2, flags) 2571301Sbill struct wordent *p1, *p2; 2581301Sbill int flags; 2591301Sbill { 2601301Sbill register struct wordent *p; 2611301Sbill register struct command *t; 2621301Sbill int l; 2631301Sbill 2641301Sbill l = 0; 2651301Sbill for (p = p1; p != p2; p = p->next) 2661301Sbill switch (p->word[0]) { 2671301Sbill 2681301Sbill case '(': 2691301Sbill l++; 2701301Sbill continue; 2711301Sbill 2721301Sbill case ')': 2731301Sbill l--; 2741301Sbill continue; 2751301Sbill 2761301Sbill case ';': 2771301Sbill case '\n': 2781301Sbill if (l != 0) 2791301Sbill break; 2801301Sbill t = (struct command *) calloc(1, sizeof (*t)); 281*47724Sbostic t->t_dtyp = NODE_LIST; 2821301Sbill t->t_dcar = syn1a(p1, p, flags); 2831301Sbill t->t_dcdr = syntax(p->next, p2, flags); 2841301Sbill if (t->t_dcdr == 0) 2851301Sbill t->t_dcdr = t->t_dcar, t->t_dcar = 0; 2861301Sbill return (t); 2871301Sbill } 2881301Sbill return (syn1a(p1, p2, flags)); 2891301Sbill } 2901301Sbill 2911301Sbill /* 2921301Sbill * syn1a 2931301Sbill * syn1b 2941301Sbill * syn1b || syn1a 2951301Sbill */ 2961301Sbill struct command * 2971301Sbill syn1a(p1, p2, flags) 2981301Sbill struct wordent *p1, *p2; 2991301Sbill int flags; 3001301Sbill { 3011301Sbill register struct wordent *p; 3021301Sbill register struct command *t; 3031301Sbill register int l = 0; 3041301Sbill 3051301Sbill for (p = p1; p != p2; p = p->next) 3061301Sbill switch (p->word[0]) { 3071301Sbill 3081301Sbill case '(': 3091301Sbill l++; 3101301Sbill continue; 3111301Sbill 3121301Sbill case ')': 3131301Sbill l--; 3141301Sbill continue; 3151301Sbill 3161301Sbill case '|': 3171301Sbill if (p->word[1] != '|') 3181301Sbill continue; 3191301Sbill if (l == 0) { 3201301Sbill t = (struct command *) calloc(1, sizeof (*t)); 321*47724Sbostic t->t_dtyp = NODE_OR; 3221301Sbill t->t_dcar = syn1b(p1, p, flags); 3231301Sbill t->t_dcdr = syn1a(p->next, p2, flags); 3241301Sbill t->t_dflg = 0; 3251301Sbill return (t); 3261301Sbill } 3271301Sbill continue; 3281301Sbill } 3291301Sbill return (syn1b(p1, p2, flags)); 3301301Sbill } 3311301Sbill 3321301Sbill /* 3331301Sbill * syn1b 3341301Sbill * syn2 3351301Sbill * syn2 && syn1b 3361301Sbill */ 3371301Sbill struct command * 3381301Sbill syn1b(p1, p2, flags) 3391301Sbill struct wordent *p1, *p2; 3401301Sbill int flags; 3411301Sbill { 3421301Sbill register struct wordent *p; 3431301Sbill register struct command *t; 3441301Sbill register int l = 0; 3451301Sbill 3461301Sbill l = 0; 3471301Sbill for (p = p1; p != p2; p = p->next) 3481301Sbill switch (p->word[0]) { 3491301Sbill 3501301Sbill case '(': 3511301Sbill l++; 3521301Sbill continue; 3531301Sbill 3541301Sbill case ')': 3551301Sbill l--; 3561301Sbill continue; 3571301Sbill 3581301Sbill case '&': 3591301Sbill if (p->word[1] == '&' && l == 0) { 3601301Sbill t = (struct command *) calloc(1, sizeof (*t)); 361*47724Sbostic t->t_dtyp = NODE_AND; 3621301Sbill t->t_dcar = syn2(p1, p, flags); 3631301Sbill t->t_dcdr = syn1b(p->next, p2, flags); 3641301Sbill t->t_dflg = 0; 3651301Sbill return (t); 3661301Sbill } 3671301Sbill continue; 3681301Sbill } 3691301Sbill return (syn2(p1, p2, flags)); 3701301Sbill } 3711301Sbill 3721301Sbill /* 3731301Sbill * syn2 3741301Sbill * syn3 3751301Sbill * syn3 | syn2 3761301Sbill * syn3 |& syn2 3771301Sbill */ 3781301Sbill struct command * 3791301Sbill syn2(p1, p2, flags) 3801301Sbill struct wordent *p1, *p2; 3811301Sbill int flags; 3821301Sbill { 3831301Sbill register struct wordent *p, *pn; 3841301Sbill register struct command *t; 3851301Sbill register int l = 0; 3861301Sbill int f; 3871301Sbill 3881301Sbill for (p = p1; p != p2; p = p->next) 3891301Sbill switch (p->word[0]) { 3901301Sbill 3911301Sbill case '(': 3921301Sbill l++; 3931301Sbill continue; 3941301Sbill 3951301Sbill case ')': 3961301Sbill l--; 3971301Sbill continue; 3981301Sbill 3991301Sbill case '|': 4001301Sbill if (l != 0) 4011301Sbill continue; 4021301Sbill t = (struct command *) calloc(1, sizeof (*t)); 4031301Sbill f = flags | POUT; 4041301Sbill pn = p->next; 4051301Sbill if (pn != p2 && pn->word[0] == '&') { 4061301Sbill f |= PDIAG; 407*47724Sbostic t->t_dflg |= F_STDERR; 4081301Sbill } 409*47724Sbostic t->t_dtyp = NODE_PIPE; 4101301Sbill t->t_dcar = syn3(p1, p, f); 4111301Sbill if (pn != p2 && pn->word[0] == '&') 4121301Sbill p = pn; 4131301Sbill t->t_dcdr = syn2(p->next, p2, flags | PIN); 4141301Sbill return (t); 4151301Sbill } 4161301Sbill return (syn3(p1, p2, flags)); 4171301Sbill } 4181301Sbill 4191301Sbill char *RELPAR = "<>()"; 4201301Sbill 4211301Sbill /* 4221301Sbill * syn3 4231301Sbill * ( syn0 ) [ < in ] [ > out ] 4241301Sbill * word word* [ < in ] [ > out ] 4251301Sbill * KEYWORD ( word* ) word* [ < in ] [ > out ] 4261301Sbill * 4271301Sbill * KEYWORD = (@ exit foreach if set switch test while) 4281301Sbill */ 4291301Sbill struct command * 4301301Sbill syn3(p1, p2, flags) 4311301Sbill struct wordent *p1, *p2; 4321301Sbill int flags; 4331301Sbill { 4341301Sbill register struct wordent *p; 4351301Sbill struct wordent *lp, *rp; 4361301Sbill register struct command *t; 4371301Sbill register int l; 4381301Sbill char **av; 4391301Sbill int n, c; 4401301Sbill bool specp = 0; 4411301Sbill 4421301Sbill if (p1 != p2) { 4431301Sbill p = p1; 4441301Sbill again: 4451301Sbill switch (srchx(p->word)) { 4461301Sbill 447*47724Sbostic case T_ELSE: 4481301Sbill p = p->next; 4491301Sbill if (p != p2) 4501301Sbill goto again; 4511301Sbill break; 4521301Sbill 453*47724Sbostic case T_EXIT: 454*47724Sbostic case T_FOREACH: 455*47724Sbostic case T_IF: 456*47724Sbostic case T_LET: 457*47724Sbostic case T_SET: 458*47724Sbostic case T_SWITCH: 459*47724Sbostic case T_WHILE: 4601301Sbill specp = 1; 4611301Sbill break; 4621301Sbill } 4631301Sbill } 4641301Sbill n = 0; 4651301Sbill l = 0; 4661301Sbill for (p = p1; p != p2; p = p->next) 4671301Sbill switch (p->word[0]) { 4681301Sbill 4691301Sbill case '(': 4701301Sbill if (specp) 4711301Sbill n++; 4721301Sbill l++; 4731301Sbill continue; 4741301Sbill 4751301Sbill case ')': 4761301Sbill if (specp) 4771301Sbill n++; 4781301Sbill l--; 4791301Sbill continue; 4801301Sbill 4811301Sbill case '>': 4821301Sbill case '<': 4831301Sbill if (l != 0) { 4841301Sbill if (specp) 4851301Sbill n++; 4861301Sbill continue; 4871301Sbill } 4881301Sbill if (p->next == p2) 4891301Sbill continue; 49047419Sbostic if (index(RELPAR, p->next->word[0])) 4911301Sbill continue; 4921301Sbill n--; 4931301Sbill continue; 4941301Sbill 4951301Sbill default: 4961301Sbill if (!specp && l != 0) 4971301Sbill continue; 4981301Sbill n++; 4991301Sbill continue; 5001301Sbill } 5011301Sbill if (n < 0) 5021301Sbill n = 0; 5031301Sbill t = (struct command *) calloc(1, sizeof (*t)); 50417511Sedward av = (char **) calloc((unsigned) (n + 1), sizeof (char **)); 5051301Sbill t->t_dcom = av; 5061301Sbill n = 0; 5071301Sbill if (p2->word[0] == ')') 508*47724Sbostic t->t_dflg = F_NOFORK; 5091301Sbill lp = 0; 5101301Sbill rp = 0; 5111301Sbill l = 0; 5121301Sbill for (p = p1; p != p2; p = p->next) { 5131301Sbill c = p->word[0]; 5141301Sbill switch (c) { 5151301Sbill 5161301Sbill case '(': 5171301Sbill if (l == 0) { 5181301Sbill if (lp != 0 && !specp) 5191301Sbill seterr("Badly placed ("); 5201301Sbill lp = p->next; 5211301Sbill } 5221301Sbill l++; 5231301Sbill goto savep; 5241301Sbill 5251301Sbill case ')': 5261301Sbill l--; 5271301Sbill if (l == 0) 5281301Sbill rp = p; 5291301Sbill goto savep; 5301301Sbill 5311301Sbill case '>': 5321301Sbill if (l != 0) 5331301Sbill goto savep; 5341301Sbill if (p->word[1] == '>') 535*47724Sbostic t->t_dflg |= F_APPEND; 5361301Sbill if (p->next != p2 && eq(p->next->word, "&")) { 537*47724Sbostic t->t_dflg |= F_STDERR; 538*47724Sbostic p = p->next; 5391301Sbill if (flags & (POUT|PDIAG)) 5401301Sbill goto badout; 5411301Sbill } 542*47724Sbostic if (p->next != p2 && eq(p->next->word, "!")) { 543*47724Sbostic t->t_dflg |= F_OVERWRITE; 544*47724Sbostic p = p->next; 545*47724Sbostic } 5461301Sbill if (p->next == p2) { 5471301Sbill missfile: 5481301Sbill seterr("Missing name for redirect"); 5491301Sbill continue; 5501301Sbill } 5511301Sbill p = p->next; 55247419Sbostic if (index(RELPAR, p->word[0])) 5531301Sbill goto missfile; 5541301Sbill if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit) 5551301Sbill badout: 5561301Sbill seterr("Ambiguous output redirect"); 5571301Sbill else 5581301Sbill t->t_drit = savestr(p->word); 5591301Sbill continue; 5601301Sbill 5611301Sbill case '<': 5621301Sbill if (l != 0) 5631301Sbill goto savep; 5641301Sbill if (p->word[1] == '<') 565*47724Sbostic t->t_dflg |= F_READ; 5661301Sbill if (p->next == p2) 5671301Sbill goto missfile; 5681301Sbill p = p->next; 56947419Sbostic if (index(RELPAR, p->word[0])) 5701301Sbill goto missfile; 571*47724Sbostic if ((flags & PHERE) && (t->t_dflg & F_READ)) 5721301Sbill seterr("Can't << within ()'s"); 5731301Sbill else if ((flags & PIN) || t->t_dlef) 5741301Sbill seterr("Ambiguous input redirect"); 5751301Sbill else 5761301Sbill t->t_dlef = savestr(p->word); 5771301Sbill continue; 5781301Sbill 5791301Sbill savep: 5801301Sbill if (!specp) 5811301Sbill continue; 5821301Sbill default: 5831301Sbill if (l != 0 && !specp) 5841301Sbill continue; 5851301Sbill if (err == 0) 5861301Sbill av[n] = savestr(p->word); 5871301Sbill n++; 5881301Sbill continue; 5891301Sbill } 5901301Sbill } 5911301Sbill if (lp != 0 && !specp) { 5921301Sbill if (n != 0) 5931301Sbill seterr("Badly placed ()'s"); 594*47724Sbostic t->t_dtyp = NODE_PAREN; 5951301Sbill t->t_dspr = syn0(lp, rp, PHERE); 5961301Sbill } else { 5971301Sbill if (n == 0) 5981301Sbill seterr("Invalid null command"); 599*47724Sbostic t->t_dtyp = NODE_COMMAND; 6001301Sbill } 6011301Sbill return (t); 6021301Sbill } 6031301Sbill 6041301Sbill freesyn(t) 6051301Sbill register struct command *t; 6061301Sbill { 6071301Sbill register char **v; 6081301Sbill 6091301Sbill if (t == 0) 6101301Sbill return; 6111301Sbill switch (t->t_dtyp) { 6121301Sbill 613*47724Sbostic case NODE_COMMAND: 6141301Sbill for (v = t->t_dcom; *v; v++) 61517511Sedward XFREE(*v) 61617511Sedward XFREE((char *)t->t_dcom) 6171301Sbill goto lr; 6181301Sbill 619*47724Sbostic case NODE_PAREN: 6201301Sbill freesyn(t->t_dspr); 6211301Sbill /* fall into ... */ 6221301Sbill 6231301Sbill lr: 62417511Sedward XFREE(t->t_dlef) 62517511Sedward XFREE(t->t_drit) 6261301Sbill break; 6271301Sbill 628*47724Sbostic case NODE_AND: 629*47724Sbostic case NODE_OR: 630*47724Sbostic case NODE_PIPE: 631*47724Sbostic case NODE_LIST: 632*47724Sbostic freesyn(t->t_dcar); 633*47724Sbostic freesyn(t->t_dcdr); 6341301Sbill break; 6351301Sbill } 63617511Sedward XFREE((char *)t) 6371301Sbill } 638