1*47823Sbostic /*- 2*47823Sbostic * Copyright (c) 1980, 1991 The Regents of the University of California. 3*47823Sbostic * All rights reserved. 4*47823Sbostic * 5*47823Sbostic * %sccs.include.redist.c% 621939Sdist */ 721939Sdist 817511Sedward #ifndef lint 9*47823Sbostic static char sccsid[] = "@(#)parse.c 5.6 (Berkeley) 04/04/91"; 10*47823Sbostic #endif /* not lint */ 111301Sbill 121301Sbill #include "sh.h" 131301Sbill 141301Sbill /* 151301Sbill * C shell 161301Sbill */ 171301Sbill 181301Sbill /* 191301Sbill * Perform aliasing on the word list lex 201301Sbill * Do a (very rudimentary) parse to separate into commands. 211301Sbill * If word 0 of a command has an alias, do it. 221301Sbill * Repeat a maximum of 20 times. 231301Sbill */ 241301Sbill alias(lex) 251301Sbill register struct wordent *lex; 261301Sbill { 271301Sbill int aleft = 21; 281301Sbill jmp_buf osetexit; 291301Sbill 301301Sbill getexit(osetexit); 3147724Sbostic (void)setjmp(reslab); 321301Sbill if (haderr) { 331301Sbill resexit(osetexit); 3447724Sbostic longjmp(reslab, 0); 351301Sbill } 361301Sbill if (--aleft == 0) 371301Sbill error("Alias loop"); 381301Sbill asyntax(lex->next, lex); 391301Sbill resexit(osetexit); 401301Sbill } 411301Sbill 421301Sbill asyntax(p1, p2) 431301Sbill register struct wordent *p1, *p2; 441301Sbill { 451301Sbill 461301Sbill while (p1 != p2) 4747419Sbostic if (index(";&\n", p1->word[0])) 481301Sbill p1 = p1->next; 491301Sbill else { 501301Sbill asyn0(p1, p2); 511301Sbill return; 521301Sbill } 531301Sbill } 541301Sbill 551301Sbill asyn0(p1, p2) 561301Sbill struct wordent *p1; 571301Sbill register struct wordent *p2; 581301Sbill { 591301Sbill register struct wordent *p; 601301Sbill register int l = 0; 611301Sbill 621301Sbill for (p = p1; p != p2; p = p->next) 631301Sbill switch (p->word[0]) { 641301Sbill 651301Sbill case '(': 661301Sbill l++; 671301Sbill continue; 681301Sbill 691301Sbill case ')': 701301Sbill l--; 711301Sbill if (l < 0) 721301Sbill error("Too many )'s"); 731301Sbill continue; 741301Sbill 751301Sbill case '>': 761301Sbill if (p->next != p2 && eq(p->next->word, "&")) 771301Sbill p = p->next; 781301Sbill continue; 791301Sbill 801301Sbill case '&': 811301Sbill case '|': 821301Sbill case ';': 831301Sbill case '\n': 841301Sbill if (l != 0) 851301Sbill continue; 861301Sbill asyn3(p1, p); 871301Sbill asyntax(p->next, p2); 881301Sbill return; 891301Sbill } 901301Sbill if (l == 0) 911301Sbill asyn3(p1, p2); 921301Sbill } 931301Sbill 941301Sbill asyn3(p1, p2) 951301Sbill struct wordent *p1; 961301Sbill register struct wordent *p2; 971301Sbill { 981301Sbill register struct varent *ap; 991301Sbill struct wordent alout; 1001301Sbill register bool redid; 1011301Sbill 1021301Sbill if (p1 == p2) 1031301Sbill return; 1041301Sbill if (p1->word[0] == '(') { 1051301Sbill for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 1061301Sbill if (p2 == p1) 1071301Sbill return; 1081301Sbill if (p2 == p1->next) 1091301Sbill return; 1101301Sbill asyn0(p1->next, p2); 1111301Sbill return; 1121301Sbill } 1131301Sbill ap = adrof1(p1->word, &aliases); 1141301Sbill if (ap == 0) 1151301Sbill return; 1161301Sbill alhistp = p1->prev; 1171301Sbill alhistt = p2; 1181301Sbill alvec = ap->vec; 1191301Sbill redid = lex(&alout); 1201301Sbill alhistp = alhistt = 0; 1211301Sbill alvec = 0; 1221301Sbill if (err) { 1231301Sbill freelex(&alout); 1241301Sbill error(err); 1251301Sbill } 1261301Sbill if (p1->word[0] && eq(p1->word, alout.next->word)) { 1271301Sbill char *cp = alout.next->word; 1281301Sbill 1291301Sbill alout.next->word = strspl("\200", cp); 13017511Sedward XFREE(cp) 1311301Sbill } 1321301Sbill p1 = freenod(p1, redid ? p2 : p1->next); 1331301Sbill if (alout.next != &alout) { 1341301Sbill p1->next->prev = alout.prev->prev; 1351301Sbill alout.prev->prev->next = p1->next; 1361301Sbill alout.next->prev = p1; 1371301Sbill p1->next = alout.next; 13817511Sedward XFREE(alout.prev->word) 13917511Sedward XFREE((char *)alout.prev) 1401301Sbill } 14147724Sbostic longjmp(reslab, 0); /* throw! */ 1421301Sbill } 1431301Sbill 1441301Sbill struct wordent * 1451301Sbill freenod(p1, p2) 1461301Sbill register struct wordent *p1, *p2; 1471301Sbill { 1481301Sbill register struct wordent *retp = p1->prev; 1491301Sbill 1501301Sbill while (p1 != p2) { 15117511Sedward XFREE(p1->word) 1521301Sbill p1 = p1->next; 15317511Sedward XFREE((char *)p1->prev) 1541301Sbill } 1551301Sbill retp->next = p2; 1561301Sbill p2->prev = retp; 1571301Sbill return (retp); 1581301Sbill } 1591301Sbill 1601301Sbill #define PHERE 1 1611301Sbill #define PIN 2 1621301Sbill #define POUT 4 1631301Sbill #define PDIAG 8 1641301Sbill 1651301Sbill /* 1661301Sbill * syntax 1671301Sbill * empty 1681301Sbill * syn0 1691301Sbill */ 1701301Sbill struct command * 1711301Sbill syntax(p1, p2, flags) 1721301Sbill register struct wordent *p1, *p2; 1731301Sbill int flags; 1741301Sbill { 1751301Sbill 1761301Sbill while (p1 != p2) 17747419Sbostic if (index(";&\n", p1->word[0])) 1781301Sbill p1 = p1->next; 1791301Sbill else 1801301Sbill return (syn0(p1, p2, flags)); 1811301Sbill return (0); 1821301Sbill } 1831301Sbill 1841301Sbill /* 1851301Sbill * syn0 1861301Sbill * syn1 1871301Sbill * syn1 & syntax 1881301Sbill */ 1891301Sbill struct command * 1901301Sbill syn0(p1, p2, flags) 1911301Sbill struct wordent *p1, *p2; 1921301Sbill int flags; 1931301Sbill { 1941301Sbill register struct wordent *p; 1951301Sbill register struct command *t, *t1; 1961301Sbill int l; 1971301Sbill 1981301Sbill l = 0; 1991301Sbill for (p = p1; p != p2; p = p->next) 2001301Sbill switch (p->word[0]) { 2011301Sbill 2021301Sbill case '(': 2031301Sbill l++; 2041301Sbill continue; 2051301Sbill 2061301Sbill case ')': 2071301Sbill l--; 2081301Sbill if (l < 0) 2091301Sbill seterr("Too many )'s"); 2101301Sbill continue; 2111301Sbill 2121301Sbill case '|': 2131301Sbill if (p->word[1] == '|') 2141301Sbill continue; 2151301Sbill /* fall into ... */ 2161301Sbill 2171301Sbill case '>': 2181301Sbill if (p->next != p2 && eq(p->next->word, "&")) 2191301Sbill p = p->next; 2201301Sbill continue; 2211301Sbill 2221301Sbill case '&': 2231301Sbill if (l != 0) 2241301Sbill break; 2251301Sbill if (p->word[1] == '&') 2261301Sbill continue; 2271301Sbill t1 = syn1(p1, p, flags); 22847724Sbostic if (t1->t_dtyp == NODE_LIST || 22947724Sbostic t1->t_dtyp == NODE_AND || 23047724Sbostic t1->t_dtyp == NODE_OR) { 2311301Sbill t = (struct command *) calloc(1, sizeof (*t)); 23247724Sbostic t->t_dtyp = NODE_PAREN; 23347724Sbostic t->t_dflg = F_AMPERSAND|F_NOINTERRUPT; 2341301Sbill t->t_dspr = t1; 2351301Sbill t1 = t; 2361301Sbill } else 23747724Sbostic t1->t_dflg |= F_AMPERSAND|F_NOINTERRUPT; 2381301Sbill t = (struct command *) calloc(1, sizeof (*t)); 23947724Sbostic t->t_dtyp = NODE_LIST; 2401301Sbill t->t_dflg = 0; 2411301Sbill t->t_dcar = t1; 2421301Sbill t->t_dcdr = syntax(p, p2, flags); 2431301Sbill return(t); 2441301Sbill } 2451301Sbill if (l == 0) 2461301Sbill return (syn1(p1, p2, flags)); 2471301Sbill seterr("Too many ('s"); 2481301Sbill return (0); 2491301Sbill } 2501301Sbill 2511301Sbill /* 2521301Sbill * syn1 2531301Sbill * syn1a 2541301Sbill * syn1a ; syntax 2551301Sbill */ 2561301Sbill struct command * 2571301Sbill syn1(p1, p2, flags) 2581301Sbill struct wordent *p1, *p2; 2591301Sbill int flags; 2601301Sbill { 2611301Sbill register struct wordent *p; 2621301Sbill register struct command *t; 2631301Sbill int l; 2641301Sbill 2651301Sbill l = 0; 2661301Sbill for (p = p1; p != p2; p = p->next) 2671301Sbill switch (p->word[0]) { 2681301Sbill 2691301Sbill case '(': 2701301Sbill l++; 2711301Sbill continue; 2721301Sbill 2731301Sbill case ')': 2741301Sbill l--; 2751301Sbill continue; 2761301Sbill 2771301Sbill case ';': 2781301Sbill case '\n': 2791301Sbill if (l != 0) 2801301Sbill break; 2811301Sbill t = (struct command *) calloc(1, sizeof (*t)); 28247724Sbostic t->t_dtyp = NODE_LIST; 2831301Sbill t->t_dcar = syn1a(p1, p, flags); 2841301Sbill t->t_dcdr = syntax(p->next, p2, flags); 2851301Sbill if (t->t_dcdr == 0) 2861301Sbill t->t_dcdr = t->t_dcar, t->t_dcar = 0; 2871301Sbill return (t); 2881301Sbill } 2891301Sbill return (syn1a(p1, p2, flags)); 2901301Sbill } 2911301Sbill 2921301Sbill /* 2931301Sbill * syn1a 2941301Sbill * syn1b 2951301Sbill * syn1b || syn1a 2961301Sbill */ 2971301Sbill struct command * 2981301Sbill syn1a(p1, p2, flags) 2991301Sbill struct wordent *p1, *p2; 3001301Sbill int flags; 3011301Sbill { 3021301Sbill register struct wordent *p; 3031301Sbill register struct command *t; 3041301Sbill register int l = 0; 3051301Sbill 3061301Sbill for (p = p1; p != p2; p = p->next) 3071301Sbill switch (p->word[0]) { 3081301Sbill 3091301Sbill case '(': 3101301Sbill l++; 3111301Sbill continue; 3121301Sbill 3131301Sbill case ')': 3141301Sbill l--; 3151301Sbill continue; 3161301Sbill 3171301Sbill case '|': 3181301Sbill if (p->word[1] != '|') 3191301Sbill continue; 3201301Sbill if (l == 0) { 3211301Sbill t = (struct command *) calloc(1, sizeof (*t)); 32247724Sbostic t->t_dtyp = NODE_OR; 3231301Sbill t->t_dcar = syn1b(p1, p, flags); 3241301Sbill t->t_dcdr = syn1a(p->next, p2, flags); 3251301Sbill t->t_dflg = 0; 3261301Sbill return (t); 3271301Sbill } 3281301Sbill continue; 3291301Sbill } 3301301Sbill return (syn1b(p1, p2, flags)); 3311301Sbill } 3321301Sbill 3331301Sbill /* 3341301Sbill * syn1b 3351301Sbill * syn2 3361301Sbill * syn2 && syn1b 3371301Sbill */ 3381301Sbill struct command * 3391301Sbill syn1b(p1, p2, flags) 3401301Sbill struct wordent *p1, *p2; 3411301Sbill int flags; 3421301Sbill { 3431301Sbill register struct wordent *p; 3441301Sbill register struct command *t; 3451301Sbill register int l = 0; 3461301Sbill 3471301Sbill l = 0; 3481301Sbill for (p = p1; p != p2; p = p->next) 3491301Sbill switch (p->word[0]) { 3501301Sbill 3511301Sbill case '(': 3521301Sbill l++; 3531301Sbill continue; 3541301Sbill 3551301Sbill case ')': 3561301Sbill l--; 3571301Sbill continue; 3581301Sbill 3591301Sbill case '&': 3601301Sbill if (p->word[1] == '&' && l == 0) { 3611301Sbill t = (struct command *) calloc(1, sizeof (*t)); 36247724Sbostic t->t_dtyp = NODE_AND; 3631301Sbill t->t_dcar = syn2(p1, p, flags); 3641301Sbill t->t_dcdr = syn1b(p->next, p2, flags); 3651301Sbill t->t_dflg = 0; 3661301Sbill return (t); 3671301Sbill } 3681301Sbill continue; 3691301Sbill } 3701301Sbill return (syn2(p1, p2, flags)); 3711301Sbill } 3721301Sbill 3731301Sbill /* 3741301Sbill * syn2 3751301Sbill * syn3 3761301Sbill * syn3 | syn2 3771301Sbill * syn3 |& syn2 3781301Sbill */ 3791301Sbill struct command * 3801301Sbill syn2(p1, p2, flags) 3811301Sbill struct wordent *p1, *p2; 3821301Sbill int flags; 3831301Sbill { 3841301Sbill register struct wordent *p, *pn; 3851301Sbill register struct command *t; 3861301Sbill register int l = 0; 3871301Sbill int f; 3881301Sbill 3891301Sbill for (p = p1; p != p2; p = p->next) 3901301Sbill switch (p->word[0]) { 3911301Sbill 3921301Sbill case '(': 3931301Sbill l++; 3941301Sbill continue; 3951301Sbill 3961301Sbill case ')': 3971301Sbill l--; 3981301Sbill continue; 3991301Sbill 4001301Sbill case '|': 4011301Sbill if (l != 0) 4021301Sbill continue; 4031301Sbill t = (struct command *) calloc(1, sizeof (*t)); 4041301Sbill f = flags | POUT; 4051301Sbill pn = p->next; 4061301Sbill if (pn != p2 && pn->word[0] == '&') { 4071301Sbill f |= PDIAG; 40847724Sbostic t->t_dflg |= F_STDERR; 4091301Sbill } 41047724Sbostic t->t_dtyp = NODE_PIPE; 4111301Sbill t->t_dcar = syn3(p1, p, f); 4121301Sbill if (pn != p2 && pn->word[0] == '&') 4131301Sbill p = pn; 4141301Sbill t->t_dcdr = syn2(p->next, p2, flags | PIN); 4151301Sbill return (t); 4161301Sbill } 4171301Sbill return (syn3(p1, p2, flags)); 4181301Sbill } 4191301Sbill 4201301Sbill char *RELPAR = "<>()"; 4211301Sbill 4221301Sbill /* 4231301Sbill * syn3 4241301Sbill * ( syn0 ) [ < in ] [ > out ] 4251301Sbill * word word* [ < in ] [ > out ] 4261301Sbill * KEYWORD ( word* ) word* [ < in ] [ > out ] 4271301Sbill * 4281301Sbill * KEYWORD = (@ exit foreach if set switch test while) 4291301Sbill */ 4301301Sbill struct command * 4311301Sbill syn3(p1, p2, flags) 4321301Sbill struct wordent *p1, *p2; 4331301Sbill int flags; 4341301Sbill { 4351301Sbill register struct wordent *p; 4361301Sbill struct wordent *lp, *rp; 4371301Sbill register struct command *t; 4381301Sbill register int l; 4391301Sbill char **av; 4401301Sbill int n, c; 4411301Sbill bool specp = 0; 4421301Sbill 4431301Sbill if (p1 != p2) { 4441301Sbill p = p1; 4451301Sbill again: 4461301Sbill switch (srchx(p->word)) { 4471301Sbill 44847724Sbostic case T_ELSE: 4491301Sbill p = p->next; 4501301Sbill if (p != p2) 4511301Sbill goto again; 4521301Sbill break; 4531301Sbill 45447724Sbostic case T_EXIT: 45547724Sbostic case T_FOREACH: 45647724Sbostic case T_IF: 45747724Sbostic case T_LET: 45847724Sbostic case T_SET: 45947724Sbostic case T_SWITCH: 46047724Sbostic case T_WHILE: 4611301Sbill specp = 1; 4621301Sbill break; 4631301Sbill } 4641301Sbill } 4651301Sbill n = 0; 4661301Sbill l = 0; 4671301Sbill for (p = p1; p != p2; p = p->next) 4681301Sbill switch (p->word[0]) { 4691301Sbill 4701301Sbill case '(': 4711301Sbill if (specp) 4721301Sbill n++; 4731301Sbill l++; 4741301Sbill continue; 4751301Sbill 4761301Sbill case ')': 4771301Sbill if (specp) 4781301Sbill n++; 4791301Sbill l--; 4801301Sbill continue; 4811301Sbill 4821301Sbill case '>': 4831301Sbill case '<': 4841301Sbill if (l != 0) { 4851301Sbill if (specp) 4861301Sbill n++; 4871301Sbill continue; 4881301Sbill } 4891301Sbill if (p->next == p2) 4901301Sbill continue; 49147419Sbostic if (index(RELPAR, p->next->word[0])) 4921301Sbill continue; 4931301Sbill n--; 4941301Sbill continue; 4951301Sbill 4961301Sbill default: 4971301Sbill if (!specp && l != 0) 4981301Sbill continue; 4991301Sbill n++; 5001301Sbill continue; 5011301Sbill } 5021301Sbill if (n < 0) 5031301Sbill n = 0; 5041301Sbill t = (struct command *) calloc(1, sizeof (*t)); 50517511Sedward av = (char **) calloc((unsigned) (n + 1), sizeof (char **)); 5061301Sbill t->t_dcom = av; 5071301Sbill n = 0; 5081301Sbill if (p2->word[0] == ')') 50947724Sbostic t->t_dflg = F_NOFORK; 5101301Sbill lp = 0; 5111301Sbill rp = 0; 5121301Sbill l = 0; 5131301Sbill for (p = p1; p != p2; p = p->next) { 5141301Sbill c = p->word[0]; 5151301Sbill switch (c) { 5161301Sbill 5171301Sbill case '(': 5181301Sbill if (l == 0) { 5191301Sbill if (lp != 0 && !specp) 5201301Sbill seterr("Badly placed ("); 5211301Sbill lp = p->next; 5221301Sbill } 5231301Sbill l++; 5241301Sbill goto savep; 5251301Sbill 5261301Sbill case ')': 5271301Sbill l--; 5281301Sbill if (l == 0) 5291301Sbill rp = p; 5301301Sbill goto savep; 5311301Sbill 5321301Sbill case '>': 5331301Sbill if (l != 0) 5341301Sbill goto savep; 5351301Sbill if (p->word[1] == '>') 53647724Sbostic t->t_dflg |= F_APPEND; 5371301Sbill if (p->next != p2 && eq(p->next->word, "&")) { 53847724Sbostic t->t_dflg |= F_STDERR; 53947724Sbostic p = p->next; 5401301Sbill if (flags & (POUT|PDIAG)) 5411301Sbill goto badout; 5421301Sbill } 54347724Sbostic if (p->next != p2 && eq(p->next->word, "!")) { 54447724Sbostic t->t_dflg |= F_OVERWRITE; 54547724Sbostic p = p->next; 54647724Sbostic } 5471301Sbill if (p->next == p2) { 5481301Sbill missfile: 5491301Sbill seterr("Missing name for redirect"); 5501301Sbill continue; 5511301Sbill } 5521301Sbill p = p->next; 55347419Sbostic if (index(RELPAR, p->word[0])) 5541301Sbill goto missfile; 5551301Sbill if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit) 5561301Sbill badout: 5571301Sbill seterr("Ambiguous output redirect"); 5581301Sbill else 5591301Sbill t->t_drit = savestr(p->word); 5601301Sbill continue; 5611301Sbill 5621301Sbill case '<': 5631301Sbill if (l != 0) 5641301Sbill goto savep; 5651301Sbill if (p->word[1] == '<') 56647724Sbostic t->t_dflg |= F_READ; 5671301Sbill if (p->next == p2) 5681301Sbill goto missfile; 5691301Sbill p = p->next; 57047419Sbostic if (index(RELPAR, p->word[0])) 5711301Sbill goto missfile; 57247724Sbostic if ((flags & PHERE) && (t->t_dflg & F_READ)) 5731301Sbill seterr("Can't << within ()'s"); 5741301Sbill else if ((flags & PIN) || t->t_dlef) 5751301Sbill seterr("Ambiguous input redirect"); 5761301Sbill else 5771301Sbill t->t_dlef = savestr(p->word); 5781301Sbill continue; 5791301Sbill 5801301Sbill savep: 5811301Sbill if (!specp) 5821301Sbill continue; 5831301Sbill default: 5841301Sbill if (l != 0 && !specp) 5851301Sbill continue; 5861301Sbill if (err == 0) 5871301Sbill av[n] = savestr(p->word); 5881301Sbill n++; 5891301Sbill continue; 5901301Sbill } 5911301Sbill } 5921301Sbill if (lp != 0 && !specp) { 5931301Sbill if (n != 0) 5941301Sbill seterr("Badly placed ()'s"); 59547724Sbostic t->t_dtyp = NODE_PAREN; 5961301Sbill t->t_dspr = syn0(lp, rp, PHERE); 5971301Sbill } else { 5981301Sbill if (n == 0) 5991301Sbill seterr("Invalid null command"); 60047724Sbostic t->t_dtyp = NODE_COMMAND; 6011301Sbill } 6021301Sbill return (t); 6031301Sbill } 6041301Sbill 6051301Sbill freesyn(t) 6061301Sbill register struct command *t; 6071301Sbill { 6081301Sbill register char **v; 6091301Sbill 6101301Sbill if (t == 0) 6111301Sbill return; 6121301Sbill switch (t->t_dtyp) { 6131301Sbill 61447724Sbostic case NODE_COMMAND: 6151301Sbill for (v = t->t_dcom; *v; v++) 61617511Sedward XFREE(*v) 61717511Sedward XFREE((char *)t->t_dcom) 6181301Sbill goto lr; 6191301Sbill 62047724Sbostic case NODE_PAREN: 6211301Sbill freesyn(t->t_dspr); 6221301Sbill /* fall into ... */ 6231301Sbill 6241301Sbill lr: 62517511Sedward XFREE(t->t_dlef) 62617511Sedward XFREE(t->t_drit) 6271301Sbill break; 6281301Sbill 62947724Sbostic case NODE_AND: 63047724Sbostic case NODE_OR: 63147724Sbostic case NODE_PIPE: 63247724Sbostic case NODE_LIST: 63347724Sbostic freesyn(t->t_dcar); 63447724Sbostic freesyn(t->t_dcdr); 6351301Sbill break; 6361301Sbill } 63717511Sedward XFREE((char *)t) 6381301Sbill } 639