15155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* $OpenBSD: syn.c,v 1.28 2008/07/23 16:34:38 jaredy Exp $ */ 25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*- 4c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 5c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * 2011, 2012 65155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Thorsten Glaser <tg@mirbsd.org> 75155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 85155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices 95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission 105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un- 115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify, 125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence. 135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor 165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event 175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect, 185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out 195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such 205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out 215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended. 225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h" 255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 26c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.88 2012/12/28 02:28:39 tg Exp $"); 275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct nesting_state { 295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int start_token; /* token than began nesting (eg, FOR) */ 305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int start_line; /* line nesting began on */ 315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 33c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstruct yyrecursive_state { 34c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct yyrecursive_state *next; 35c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct ioword **old_herep; 36c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int old_symbol; 37c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int old_salias; 38c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int old_nesting_type; 39c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bool old_reject; 40c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}; 41c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void yyparse(void); 435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *pipeline(int); 445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *andor(void); 4503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic struct op *c_list(bool); 465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct ioword *synio(int); 475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *nested(int, int, int); 485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *get_command(int); 495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *dogroup(void); 505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *thenpart(void); 515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *elsepart(void); 525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *caselist(void); 535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *casepart(int); 545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *function_body(char *, bool); 555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char **wordlist(void); 565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *block(int, struct op *, struct op *, char **); 575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *newtp(int); 585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void syntaxerr(const char *) MKSH_A_NORETURN; 595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void nesting_push(struct nesting_state *, int); 605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void nesting_pop(struct nesting_state *); 61c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int assign_command(const char *); 625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int inalias(struct source *); 635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Test_op dbtestp_isa(Test_env *, Test_meta); 645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *dbtestp_getopnd(Test_env *, Test_op, bool); 655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int dbtestp_eval(Test_env *, Test_op, const char *, 665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *, bool); 675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void dbtestp_error(Test_env *, int, const char *) MKSH_A_NORETURN; 685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op *outtree; /* yyparse output */ 705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct nesting_state nesting; /* \n changed to ; */ 715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic bool reject; /* token(cf) gets symbol again */ 7303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int symbol; /* yylex value */ 74c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int sALIAS = ALIAS; /* 0 in yyrecursive */ 755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define REJECT (reject = true) 7703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define ACCEPT (reject = false) 785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define token(cf) ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf))) 795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define tpeek(cf) ((reject) ? (symbol) : (REJECT, symbol = yylex(cf))) 8003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define musthave(c,cf) do { if (token(cf) != (c)) syntaxerr(NULL); } while (/* CONSTCOND */ 0) 815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 82c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const char Tcbrace[] = "}"; 83c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const char Tesac[] = "esac"; 84c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruyyparse(void) 875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ACCEPT; 915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru outtree = c_list(source->type == SSTRING); 935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = tpeek(0); 945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == 0 && !outtree) 955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru outtree = newtp(TEOF); 965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (c != '\n' && c != 0) 975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru syntaxerr(NULL); 985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querupipeline(int cf) 1025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t, *p, *tl = NULL; 1045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = get_command(cf); 1065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t != NULL) { 1075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (token(0) == '|') { 1085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p = get_command(CONTIN)) == NULL) 1095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru syntaxerr(NULL); 1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tl == NULL) 1115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = tl = block(TPIPE, t, p, NOWORDS); 1125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 1135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tl = tl->right = block(TPIPE, tl->right, p, NOWORDS); 1145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru REJECT; 1165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (t); 1185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 1215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruandor(void) 1225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t, *p; 1245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 1255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = pipeline(0); 1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t != NULL) { 1285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((c = token(0)) == LOGAND || c == LOGOR) { 1295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p = pipeline(CONTIN)) == NULL) 1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru syntaxerr(NULL); 1315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS); 1325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru REJECT; 1345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (t); 1365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 13903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrac_list(bool multi) 1405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t = NULL, *p, *tl = NULL; 14203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int c; 14303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool have_sep; 1445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (/* CONSTCOND */ 1) { 1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = andor(); 14703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 14803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Token has always been read/rejected at this point, so 1495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * we don't worry about what flags to pass token() 1505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = token(0); 15203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra have_sep = true; 1535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '\n' && (multi || inalias(source))) { 15403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!p) 15503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* ignore blank lines */ 1565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 1575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (!p) 1585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (c == '&' || c == COPROC) 1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = block(c == '&' ? TASYNC : TCOPROC, 1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p, NOBLOCK, NOWORDS); 1625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (c != ';') 16303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra have_sep = false; 1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!t) 1655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = p; 1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (!tl) 1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = tl = block(TLIST, t, p, NOWORDS); 1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tl = tl->right = block(TLIST, tl->right, p, NOWORDS); 1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!have_sep) 1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru REJECT; 1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (t); 1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct ioword * 1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusynio(int cf) 1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct ioword *iop; 18103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra static struct ioword *nextiop; 1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool ishere; 1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (nextiop != NULL) { 1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iop = nextiop; 1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nextiop = NULL; 1875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (iop); 1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tpeek(cf) != REDIR) 1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ACCEPT; 1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iop = yylval.iop; 19403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (iop->flag & IONDELIM) 19503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto gotnulldelim; 19603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ishere = (iop->flag & IOTYPE) == IOHERE; 1975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru musthave(LWORD, ishere ? HEREDELIM : 0); 1985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ishere) { 1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iop->delim = yylval.cp; 20003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*ident != 0) 20103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* unquoted */ 20203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra gotnulldelim: 2035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iop->flag |= IOEVAL; 2045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (herep > &heres[HERES - 1]) 20503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra yyerror("too many %ss\n", "<<"); 2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *herep++ = iop; 2075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iop->name = yylval.cp; 2095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (iop->flag & IOBASH) { 2115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *cp; 2125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nextiop = alloc(sizeof(*iop), ATEMP); 2145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nextiop->name = cp = alloc(5, ATEMP); 2155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (iop->unit > 9) { 2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cp++ = CHAR; 2185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cp++ = '0' + (iop->unit / 10); 2195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cp++ = CHAR; 2215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cp++ = '0' + (iop->unit % 10); 2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cp = EOS; 2235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iop->flag &= ~IOBASH; 2255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nextiop->unit = 2; 2265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nextiop->flag = IODUP; 2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nextiop->delim = NULL; 2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nextiop->heredoc = NULL; 2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (iop); 2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querunested(int type, int smark, int emark) 2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t; 2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct nesting_state old_nesting; 2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting_push(&old_nesting, smark); 2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = c_list(true); 241c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser musthave(emark, KEYWORD|sALIAS); 2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting_pop(&old_nesting); 2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (block(type, t, NOBLOCK, NOWORDS)); 2445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 246c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const char let_cmd[] = { 247c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser CHAR, 'l', CHAR, 'e', CHAR, 't', EOS 248c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}; 249c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const char setA_cmd0[] = { 250c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser CHAR, 's', CHAR, 'e', CHAR, 't', EOS 251c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}; 252c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const char setA_cmd1[] = { 253c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser CHAR, '-', CHAR, 'A', EOS 254c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}; 255c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const char setA_cmd2[] = { 256c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser CHAR, '-', CHAR, '-', EOS 257c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}; 258c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 2595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruget_command(int cf) 2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t; 263c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int c, iopn = 0, syniocf, lno; 2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct ioword *iop, **iops; 2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPtrV args, vars; 266c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char *tcp; 2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct nesting_state old_nesting; 2685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 26903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* NUFILE is small enough to leave this addition unchecked */ 27003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra iops = alloc2((NUFILE + 1), sizeof(struct ioword *), ATEMP); 2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPinit(args, 16); 2725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPinit(vars, 16); 2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 274c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser syniocf = KEYWORD|sALIAS; 275c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser switch (c = token(cf|KEYWORD|sALIAS|VARASN)) { 2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 2775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru REJECT; 2785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(iops, ATEMP); 2795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPfree(args); 2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPfree(vars); 28103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* empty line */ 28203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (NULL); 2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LWORD: 2855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case REDIR: 2865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru REJECT; 287c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser syniocf &= ~(KEYWORD|sALIAS); 2885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = newtp(TCOM); 2895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->lineno = source->line; 29003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (/* CONSTCOND */ 1) { 2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cf = (t->u.evalflags ? ARRAYVAR : 0) | 292c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (XPsize(args) == 0 ? sALIAS|VARASN : CMDWORD); 2935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (tpeek(cf)) { 2945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case REDIR: 2955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((iop = synio(cf)) != NULL) { 2965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (iopn >= NUFILE) 29703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra yyerror("too many %ss\n", 29803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "redirection"); 2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iops[iopn++] = iop; 3005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LWORD: 3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ACCEPT; 30503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 30603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * the iopn == 0 and XPsize(vars) == 0 are 3075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * dubious but AT&T ksh acts this way 3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (iopn == 0 && XPsize(vars) == 0 && 3105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPsize(args) == 0 && 3115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru assign_command(ident)) 3125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->u.evalflags = DOVACHECK; 3135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((XPsize(args) == 0 || Flag(FKEYWORD)) && 3145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru is_wdvarassign(yylval.cp)) 3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(vars, yylval.cp); 3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 3175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(args, yylval.cp); 3185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 320c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '(' /*)*/: 321c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (XPsize(args) == 0 && XPsize(vars) == 1 && 322c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser is_wdvarassign(yylval.cp)) { 323c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* wdarrassign: foo=(bar) */ 3245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ACCEPT; 32503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 326c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* manipulate the vars string */ 327c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser tcp = XPptrv(vars)[(vars.len = 0)]; 328c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* 'varname=' -> 'varname' */ 329c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser tcp[wdscan(tcp, EOS) - tcp - 3] = EOS; 330c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 331c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* construct new args strings */ 332c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser XPput(args, wdcopy(setA_cmd0, ATEMP)); 333c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser XPput(args, wdcopy(setA_cmd1, ATEMP)); 334c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser XPput(args, tcp); 335c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser XPput(args, wdcopy(setA_cmd2, ATEMP)); 336c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 337c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* slurp in words till closing paren */ 338c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser while (token(CONTIN) == LWORD) 339c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser XPput(args, yylval.cp); 340c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (symbol != /*(*/ ')') 341c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser syntaxerr(NULL); 342c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else { 343c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* 344c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Check for "> foo (echo hi)" 345c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * which AT&T ksh allows (not 346c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * POSIX, but not disallowed) 347c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser */ 348c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser afree(t, ATEMP); 349c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (XPsize(args) == 0 && 350c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser XPsize(vars) == 0) { 351c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ACCEPT; 352c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto Subshell; 353c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 354c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 355c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* must be a function */ 356c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (iopn != 0 || XPsize(args) != 1 || 357c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser XPsize(vars) != 0) 358c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser syntaxerr(NULL); 359c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ACCEPT; 360c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser musthave(/*(*/')', 0); 361c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser t = function_body(XPptrv(args)[0], false); 362c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 36303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto Leave; 3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Leave; 3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Leave: 3705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 372c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '(': /*)*/ { 373c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int subshell_nesting_type_saved; 3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Subshell: 375c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser subshell_nesting_type_saved = subshell_nesting_type; 376c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser subshell_nesting_type = ')'; 3775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = nested(TPAREN, '(', ')'); 378c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser subshell_nesting_type = subshell_nesting_type_saved; 3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 380c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 3815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '{': /*}*/ 3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = nested(TBRACE, '{', '}'); 3845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 386c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case MDPAREN: 38703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* leave KEYWORD in syniocf (allow if (( 1 )) then ...) */ 3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru lno = source->line; 3895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ACCEPT; 3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (token(LETEXPR)) { 3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LWORD: 3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 39303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '(': /*)*/ 3945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Subshell; 3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru syntaxerr(NULL); 3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = newtp(TCOM); 3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->lineno = lno; 4005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(args, wdcopy(let_cmd, ATEMP)); 4015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(args, yylval.cp); 4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case DBRACKET: /* [[ .. ]] */ 40503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */ 4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = newtp(TDBRACKET); 4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ACCEPT; 4085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { 4095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Test_env te; 4105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te.flags = TEF_DBRACKET; 4125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te.pos.av = &args; 4135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te.isa = dbtestp_isa; 4145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te.getopnd = dbtestp_getopnd; 4155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te.eval = dbtestp_eval; 4165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te.error = dbtestp_error; 4175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru test_parse(&te); 4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case FOR: 4235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case SELECT: 4245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = newtp((c == FOR) ? TFOR : TSELECT); 4255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru musthave(LWORD, ARRAYVAR); 4265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!is_wdvarname(yylval.cp, true)) 42703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra yyerror("%s: %s\n", c == FOR ? "for" : Tselect, 42803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "bad identifier"); 4295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strdupx(t->str, ident, ATEMP); 4305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting_push(&old_nesting, c); 4315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->vars = wordlist(); 4325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left = dogroup(); 4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting_pop(&old_nesting); 4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case WHILE: 4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case UNTIL: 4385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting_push(&old_nesting, c); 4395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = newtp((c == WHILE) ? TWHILE : TUNTIL); 4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left = c_list(true); 4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->right = dogroup(); 4425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting_pop(&old_nesting); 4435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case CASE: 4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = newtp(TCASE); 4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru musthave(LWORD, 0); 4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->str = yylval.cp; 4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting_push(&old_nesting, c); 4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left = caselist(); 4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting_pop(&old_nesting); 4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case IF: 4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting_push(&old_nesting, c); 4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = newtp(TIF); 4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left = c_list(true); 4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->right = thenpart(); 459c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser musthave(FI, KEYWORD|sALIAS); 4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting_pop(&old_nesting); 4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case BANG: 464c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser syniocf &= ~(KEYWORD|sALIAS); 4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = pipeline(0); 4665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t == NULL) 4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru syntaxerr(NULL); 4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = block(TBANG, NOBLOCK, t, NOWORDS); 4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TIME: 472c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser syniocf &= ~(KEYWORD|sALIAS); 4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = pipeline(0); 474c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (t && t->type == TCOM) { 4755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->str = alloc(2, ATEMP); 47603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* TF_* flags */ 47703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra t->str[0] = '\0'; 4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->str[1] = '\0'; 4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = block(TTIME, t, NOBLOCK, NOWORDS); 4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case FUNCTION: 4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru musthave(LWORD, 0); 4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = function_body(yylval.cp, true); 4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((iop = synio(syniocf)) != NULL) { 4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (iopn >= NUFILE) 49103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra yyerror("too many %ss\n", "redirection"); 4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iops[iopn++] = iop; 4935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (iopn == 0) { 4965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(iops, ATEMP); 4975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->ioact = NULL; 4985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 4995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iops[iopn++] = NULL; 50003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra iops = aresize2(iops, iopn, sizeof(struct ioword *), ATEMP); 5015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->ioact = iops; 5025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t->type == TCOM || t->type == TDBRACKET) { 5055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(args, NULL); 5065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->args = (const char **)XPclose(args); 5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(vars, NULL); 5085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->vars = (char **) XPclose(vars); 5095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPfree(args); 5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPfree(vars); 5125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (t); 5155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 5165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 5185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudogroup(void) 5195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *list; 5225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 523c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser c = token(CONTIN|KEYWORD|sALIAS); 52403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 52503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * A {...} can be used instead of do...done for for/select loops 5265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * but not for while/until loops - we don't need to check if it 5275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is a while loop because it would have been parsed as part of 5285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the conditional command list... 5295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 5305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == DO) 5315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = DONE; 5325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (c == '{') 5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = '}'; 5345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 5355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru syntaxerr(NULL); 5365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru list = c_list(true); 537c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser musthave(c, KEYWORD|sALIAS); 5385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (list); 5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 5405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruthenpart(void) 5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t; 5455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 546c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser musthave(THEN, KEYWORD|sALIAS); 5475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = newtp(0); 5485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left = c_list(true); 5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t->left == NULL) 5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru syntaxerr(NULL); 5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->right = elsepart(); 5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (t); 5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 5565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruelsepart(void) 5575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t; 5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 560c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser switch (token(KEYWORD|sALIAS|VARASN)) { 5615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case ELSE: 5625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((t = c_list(true)) == NULL) 5635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru syntaxerr(NULL); 5645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (t); 5655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case ELIF: 5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = newtp(TELIF); 5685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left = c_list(true); 5695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->right = thenpart(); 5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (t); 5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru REJECT; 5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucaselist(void) 5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t, *tl; 5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 584c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser c = token(CONTIN|KEYWORD|sALIAS); 5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* A {...} can be used instead of in...esac for case statements */ 5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == IN) 5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = ESAC; 5885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (c == '{') 5895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = '}'; 5905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 5915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru syntaxerr(NULL); 5925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = tl = NULL; 59303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* no ALIAS here */ 59403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while ((tpeek(CONTIN|KEYWORD|ESACONLY)) != c) { 5955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *tc = casepart(c); 5965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tl == NULL) 5975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = tl = tc, tl->right = NULL; 5985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 5995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tl->right = tc, tl = tc; 6005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 601c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser musthave(c, KEYWORD|sALIAS); 6025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (t); 6035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 6045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 6065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucasepart(int endtok) 6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t; 6095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPtrV ptns; 6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPinit(ptns, 16); 6125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = newtp(TPAT); 6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* no ALIAS here */ 6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (token(CONTIN | KEYWORD) != '(') 6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru REJECT; 6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do { 617c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser switch (token(0)) { 618c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case LWORD: 619c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser break; 620c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '}': 621c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case ESAC: 622c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (symbol != endtok) { 623c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser strdupx(yylval.cp, 624c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser symbol == '}' ? Tcbrace : Tesac, ATEMP); 625c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser break; 626c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 627c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 628c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser default: 629c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser syntaxerr(NULL); 630c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 6315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(ptns, yylval.cp); 6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } while (token(0) == '|'); 6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru REJECT; 6345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(ptns, NULL); 6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->vars = (char **) XPclose(ptns); 6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru musthave(')', 0); 6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left = c_list(true); 639c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 640c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* initialise to default for ;; or omitted */ 641c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser t->u.charflag = ';'; 642c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* SUSv4 requires the ;; except in the last casepart */ 643c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((tpeek(CONTIN|KEYWORD|sALIAS)) != endtok) 64403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch (symbol) { 64503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra default: 64603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra syntaxerr(NULL); 64703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case BRKEV: 648c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser t->u.charflag = '|'; 649c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (0) 650c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 65103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case BRKFT: 652c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser t->u.charflag = '&'; 653c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 654c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case BREAK: 655c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* initialised above, but we need to eat the token */ 65603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ACCEPT; 65703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 6585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (t); 6595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 6605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querufunction_body(char *name, 66303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* function foo { ... } vs foo() { .. } */ 66403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool ksh_func) 6655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 6665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *sname, *p; 6675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t; 6685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 66903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sname = wdstrip(name, 0); 67003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*- 67103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Check for valid characters in name. POSIX and AT&T ksh93 say 67203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * only allow [a-zA-Z_0-9] but this allows more as old pdkshs 67303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * have allowed more; the following were never allowed: 6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * NUL TAB NL SP " $ & ' ( ) ; < = > \ ` | 6755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * C_QUOTE covers all but adds # * ? [ ] 6765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = sname; *p; p++) 6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ctype(*p, C_QUOTE)) 67903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra yyerror("%s: %s\n", sname, "invalid function name"); 6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 68103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 68203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Note that POSIX allows only compound statements after foo(), 68303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * sh and AT&T ksh allow any command, go with the later since it 68403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * shouldn't break anything. However, for function foo, AT&T ksh 68503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * only accepts an open-brace. 6865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ksh_func) { 688c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (tpeek(CONTIN|KEYWORD|sALIAS) == '(' /*)*/) { 689c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* function foo () { //}*/ 6905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ACCEPT; 6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru musthave(')', 0); 6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* degrade to POSIX function */ 6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_func = false; 6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 695c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser musthave('{' /*}*/, CONTIN|KEYWORD|sALIAS); 6965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru REJECT; 6975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = newtp(TFUNCT); 7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->str = sname; 70103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra t->u.ksh_func = tobool(ksh_func); 7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->lineno = source->line; 7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((t->left = get_command(CONTIN)) == NULL) { 7055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *tv; 7065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 70703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Probably something like foo() followed by EOF or ';'. 7085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This is accepted by sh and ksh88. 7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * To make "typeset -f foo" work reliably (so its output can 7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * be used as input), we pretend there is a colon here. 7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left = newtp(TCOM); 71303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* (2 * sizeof(char *)) is small enough */ 7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left->args = alloc(2 * sizeof(char *), ATEMP); 7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left->args[0] = tv = alloc(3, ATEMP); 7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tv[0] = CHAR; 7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tv[1] = ':'; 7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tv[2] = EOS; 7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left->args[1] = NULL; 7205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left->vars = alloc(sizeof(char *), ATEMP); 7215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left->vars[0] = NULL; 7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left->lineno = 1; 7235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (t); 7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char ** 7295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruwordlist(void) 7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 7325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPtrV args; 7335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPinit(args, 16); 7355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* POSIX does not do alias expansion here... */ 736c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((c = token(CONTIN|KEYWORD|sALIAS)) != IN) { 73703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (c != ';') 73803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* non-POSIX, but AT&T ksh accepts a ; here */ 7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru REJECT; 7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((c = token(0)) == LWORD) 7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(args, yylval.cp); 7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c != '\n' && c != ';') 7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru syntaxerr(NULL); 7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (XPsize(args) == 0) { 7475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPfree(args); 7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 7505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(args, NULL); 7515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ((char **)XPclose(args)); 7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 7545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 7565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * supporting functions 7575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querublock(int type, struct op *t1, struct op *t2, char **wp) 7615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 7625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t; 7635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = newtp(type); 7655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left = t1; 7665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->right = t2; 7675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->vars = wp; 7685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (t); 7695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 7705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 771c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const struct tokeninfo { 7725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *name; 7735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru short val; 7745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru short reserved; 7755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} tokentab[] = { 7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Reserved words */ 7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "if", IF, true }, 7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "then", THEN, true }, 7795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "else", ELSE, true }, 7805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "elif", ELIF, true }, 7815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "fi", FI, true }, 7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "case", CASE, true }, 783c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser { Tesac, ESAC, true }, 7845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "for", FOR, true }, 78503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra { Tselect, SELECT, true }, 7865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "while", WHILE, true }, 7875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "until", UNTIL, true }, 7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "do", DO, true }, 7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "done", DONE, true }, 7905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "in", IN, true }, 79103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra { Tfunction, FUNCTION, true }, 7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "time", TIME, true }, 7935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "{", '{', true }, 794c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser { Tcbrace, '}', true }, 7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "!", BANG, true }, 7965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "[[", DBRACKET, true }, 7975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Lexical tokens (0[EOF], LWORD and REDIR handled specially) */ 7985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "&&", LOGAND, false }, 7995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "||", LOGOR, false }, 8005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { ";;", BREAK, false }, 80103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra { ";|", BRKEV, false }, 80203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra { ";&", BRKFT, false }, 8035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "((", MDPAREN, false }, 8045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "|&", COPROC, false }, 8055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* and some special cases... */ 8065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { "newline", '\n', false }, 8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { NULL, 0, false } 8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 8095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 8115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinitkeywords(void) 8125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tokeninfo const *tt; 8145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *p; 8155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 81603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ktinit(APERM, &keywords, 817c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* currently 28 keywords: 75% of 64 = 2^6 */ 81803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 6); 8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (tt = tokentab; tt->name; tt++) { 8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tt->reserved) { 8215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = ktenter(&keywords, tt->name, hash(tt->name)); 8225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flag |= DEFINED|ISSET; 8235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->type = CKEYWD; 8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->val.i = tt->val; 8255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusyntaxerr(const char *what) 8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 83203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 2<<- is the longest redirection, I think */ 83303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char redir[6]; 8345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *s; 8355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tokeninfo const *tt; 8365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 8375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!what) 8395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru what = "unexpected"; 8405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru REJECT; 8415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = token(0); 8425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Again: 8435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (c) { 8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 0: 8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (nesting.start_token) { 8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = nesting.start_token; 8475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source->errline = nesting.start_line; 8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru what = "unmatched"; 8495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Again; 8505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* don't quote the EOF */ 85203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra yyerror("%s: %s %s\n", Tsynerr, "unexpected", "EOF"); 8535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* NOTREACHED */ 8545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LWORD: 8565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = snptreef(NULL, 32, "%S", yylval.cp); 8575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case REDIR: 8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = snptreef(redir, sizeof(redir), "%R", yylval.iop); 8615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 8645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (tt = tokentab; tt->name; tt++) 8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tt->val == c) 8665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tt->name) 8685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = tt->name; 8695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c > 0 && c < 256) { 8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru redir[0] = c; 8725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru redir[1] = '\0'; 8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 8745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_snprintf(redir, sizeof(redir), 8755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "?%d", c); 8765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = redir; 8775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 87903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra yyerror("%s: '%s' %s\n", Tsynerr, s, what); 8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 8835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querunesting_push(struct nesting_state *save, int tok) 8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *save = nesting; 8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting.start_token = tok; 8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting.start_line = source->line; 8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 8915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querunesting_pop(struct nesting_state *saved) 8925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting = *saved; 8945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct op * 8975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querunewtp(int type) 8985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t; 9005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = alloc(sizeof(struct op), ATEMP); 9025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->type = type; 9035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->u.evalflags = 0; 9045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->args = NULL; 9055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->vars = NULL; 9065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->ioact = NULL; 9075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->left = t->right = NULL; 9085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t->str = NULL; 9095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (t); 9105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct op * 91303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condracompile(Source *s, bool skiputf8bom) 9145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting.start_token = 0; 9165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nesting.start_line = 0; 9175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru herep = heres; 9185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source = s; 91903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (skiputf8bom) 92003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra yyskiputf8bom(); 9215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru yyparse(); 9225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (outtree); 9235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 92503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*- 92603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * This kludge exists to take care of sh/AT&T ksh oddity in which 9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the arguments of alias/export/readonly/typeset have no field 9285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * splitting, file globbing, or (normal) tilde expansion done. 9295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * AT&T ksh seems to do something similar to this since 9305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * $ touch a=a; typeset a=[ab]; echo "$a" 9315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a=[ab] 9325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * $ x=typeset; $x a=[ab]; echo "$a" 9335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a=a 9345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * $ 9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 9365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 937c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserassign_command(const char *s) 9385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!*s) 9405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 94103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return ((strcmp(s, Talias) == 0) || 942c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (strcmp(s, Texport) == 0) || 943c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (strcmp(s, Treadonly) == 0) || 94403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (strcmp(s, Ttypeset) == 0)); 9455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Check if we are in the middle of reading an alias */ 9485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 9495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinalias(struct source *s) 9505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; s && s->type == SALIAS; s = s->next) 9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(s->flags & SF_ALIASEND)) 9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 9545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 9555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 95803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 95903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Order important - indexed by Test_meta values 9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Note that ||, &&, ( and ) can't appear in as unquoted strings 9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * in normal shell input, so these can be interpreted unambiguously 9625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * in the evaluation pass. 9635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 9645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char dbtest_or[] = { CHAR, '|', CHAR, '|', EOS }; 9655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char dbtest_and[] = { CHAR, '&', CHAR, '&', EOS }; 9665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char dbtest_not[] = { CHAR, '!', EOS }; 9675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char dbtest_oparen[] = { CHAR, '(', EOS }; 9685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char dbtest_cparen[] = { CHAR, ')', EOS }; 969c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserconst char * const dbtest_tokens[] = { 9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dbtest_or, dbtest_and, dbtest_not, 9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dbtest_oparen, dbtest_cparen 9725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 973c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const char db_close[] = { CHAR, ']', CHAR, ']', EOS }; 974c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const char db_lthan[] = { CHAR, '<', EOS }; 975c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const char db_gthan[] = { CHAR, '>', EOS }; 9765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 9785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Test if the current token is a whatever. Accepts the current token if 9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * it is. Returns 0 if it is not, non-zero if it is (in the case of 9805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * TM_UNOP and TM_BINOP, the returned value is a Test_op). 9815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Test_op 9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudbtestp_isa(Test_env *te, Test_meta meta) 9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c = tpeek(ARRAYVAR | (meta == TM_BINOP ? 0 : CONTIN)); 9865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int uqword; 9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *save = NULL; 9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Test_op ret = TO_NONOP; 9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* unquoted word? */ 9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru uqword = c == LWORD && *ident; 9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (meta == TM_OR) 9945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ret = c == LOGOR ? TO_NONNULL : TO_NONOP; 9955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (meta == TM_AND) 9965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ret = c == LOGAND ? TO_NONNULL : TO_NONOP; 9975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (meta == TM_NOT) 9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ret = (uqword && !strcmp(yylval.cp, 9995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dbtest_tokens[(int)TM_NOT])) ? TO_NONNULL : TO_NONOP; 10005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (meta == TM_OPAREN) 10015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ret = c == '(' /*)*/ ? TO_NONNULL : TO_NONOP; 10025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (meta == TM_CPAREN) 10035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ret = c == /*(*/ ')' ? TO_NONNULL : TO_NONOP; 10045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (meta == TM_UNOP || meta == TM_BINOP) { 10055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (meta == TM_BINOP && c == REDIR && 10065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (yylval.iop->flag == IOREAD || yylval.iop->flag == IOWRITE)) { 10075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ret = TO_NONNULL; 10085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru save = wdcopy(yylval.iop->flag == IOREAD ? 10095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru db_lthan : db_gthan, ATEMP); 10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (uqword && (ret = test_isop(meta, ident))) 10115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru save = yylval.cp; 101203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else 101303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* meta == TM_END */ 10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ret = (uqword && !strcmp(yylval.cp, 10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru db_close)) ? TO_NONNULL : TO_NONOP; 10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ret != TO_NONOP) { 10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ACCEPT; 1018c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((unsigned int)meta < NELEM(dbtest_tokens)) 10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru save = wdcopy(dbtest_tokens[(int)meta], ATEMP); 10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (save) 10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(*te->pos.av, save); 10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (ret); 10245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char * 10275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudbtestp_getopnd(Test_env *te, Test_op op MKSH_A_UNUSED, 10285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool do_eval MKSH_A_UNUSED) 10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c = tpeek(ARRAYVAR); 10315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c != LWORD) 10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 10345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ACCEPT; 10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(*te->pos.av, yylval.cp); 10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (null); 10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudbtestp_eval(Test_env *te MKSH_A_UNUSED, Test_op op MKSH_A_UNUSED, 10435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *opnd1 MKSH_A_UNUSED, const char *opnd2 MKSH_A_UNUSED, 10445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool do_eval MKSH_A_UNUSED) 10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 10475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudbtestp_error(Test_env *te, int offset, const char *msg) 10515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te->flags |= TEF_ERROR; 10535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (offset < 0) { 10555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru REJECT; 10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Kludgy to say the least... */ 10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru symbol = LWORD; 10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru yylval.cp = *(XPptrv(*te->pos.av) + XPsize(*te->pos.av) + 10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru offset); 10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru syntaxerr(msg); 10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 106303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 106403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT 106503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 106603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef EOVERFLOW 106703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef ERANGE 106803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define EOVERFLOW ERANGE 106903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else 107003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define EOVERFLOW EINVAL 107103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 107203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 107303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 107403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrabool 107503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraparse_usec(const char *s, struct timeval *tv) 107603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 107703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct timeval tt; 107803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int i; 107903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 108003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tv->tv_sec = 0; 108103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* parse integral part */ 108203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (ksh_isdigit(*s)) { 108303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tt.tv_sec = tv->tv_sec * 10 + (*s++ - '0'); 108403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (tt.tv_sec / 10 != tv->tv_sec) { 108503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errno = EOVERFLOW; 108603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (true); 108703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 108803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tv->tv_sec = tt.tv_sec; 108903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 109003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 109103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tv->tv_usec = 0; 109203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!*s) 109303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* no decimal fraction */ 109403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (false); 109503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else if (*s++ != '.') { 109603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* junk after integral part */ 109703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errno = EINVAL; 109803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (true); 109903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 110003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 110103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* parse decimal fraction */ 110203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra i = 100000; 110303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (ksh_isdigit(*s)) { 110403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tv->tv_usec += i * (*s++ - '0'); 110503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (i == 1) 110603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 110703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra i /= 10; 110803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 110903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check for junk after fractional part */ 111003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (ksh_isdigit(*s)) 111103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++s; 111203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*s) { 111303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errno = EINVAL; 111403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (true); 111503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 111603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 111703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* end of input string reached, no errors */ 111803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (false); 111903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 112003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 112103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 112203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 112303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Helper function called from within lex.c:yylex() to parse 112403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * a COMSUB recursively using the main shell parser and lexer 112503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 112603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrachar * 1127c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaseryyrecursive(int subtype MKSH_A_UNUSED) 112803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 112903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct op *t; 113003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *cp; 1131c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct yyrecursive_state *ys; 1132c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int stok, etok; 1133c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1134c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (subtype == FUNSUB) { 1135c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser stok = '{'; 1136c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser etok = '}'; 1137c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else { 1138c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser stok = '('; 1139c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser etok = ')'; 1140c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1141c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1142c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ys = alloc(sizeof(struct yyrecursive_state), ATEMP); 114303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 114403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* tell the lexer to accept a closing parenthesis as EOD */ 1145c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ys->old_nesting_type = subshell_nesting_type; 1146c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser subshell_nesting_type = etok; 114703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 114803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* push reject state, parse recursively, pop reject state */ 1149c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ys->old_reject = reject; 1150c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ys->old_symbol = symbol; 115103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ACCEPT; 1152c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ys->old_herep = herep; 1153c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ys->old_salias = sALIAS; 1154c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser sALIAS = 0; 1155c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ys->next = e->yyrecursive_statep; 1156c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser e->yyrecursive_statep = ys; 115703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* we use TPAREN as a helper container here */ 1158c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser t = nested(TPAREN, stok, etok); 1159c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser yyrecursive_pop(false); 116003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 116103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* t->left because nested(TPAREN, ...) hides our goodies there */ 116203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra cp = snptreef(NULL, 0, "%T", t->left); 116303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tfree(t, ATEMP); 116403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 116503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (cp); 116603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 1167c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1168c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid 1169c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaseryyrecursive_pop(bool popall) 1170c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{ 1171c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct yyrecursive_state *ys; 1172c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1173c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser popnext: 1174c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!(ys = e->yyrecursive_statep)) 1175c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return; 1176c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser e->yyrecursive_statep = ys->next; 1177c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1178c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser sALIAS = ys->old_salias; 1179c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser herep = ys->old_herep; 1180c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser reject = ys->old_reject; 1181c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser symbol = ys->old_symbol; 1182c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1183c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser subshell_nesting_type = ys->old_nesting_type; 1184c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1185c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser afree(ys, ATEMP); 1186c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (popall) 1187c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto popnext; 1188c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser} 1189