1737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes/* $OpenBSD: eval.c,v 1.40 2013/09/14 20:09:30 millert Exp $ */ 25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*- 4c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 5dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 6fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes * mirabilos <m@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 26dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.219 2018/01/14 01:29:47 tg Exp $"); 275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * string expansion 305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * first pass: quoting, IFS separation, ~, ${}, $() and $(()) substitution. 325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * second pass: alternation ({,}), filename expansion (*?[]). 335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* expansion generator state */ 36811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glasertypedef struct { 37811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* not including an "int type;" member, see expand() */ 38811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* string */ 39811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser const char *str; 40811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* source */ 415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru union { 42811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* string[] */ 43811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser const char **strv; 44811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* file */ 45811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser struct shf *shf; 46811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } u; 47811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* variable in ${var...} */ 48811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser struct tbl *var; 49811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* split "$@" / call waitlast in $() */ 50811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser bool split; 515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} Expand; 525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define XBASE 0 /* scanning original */ 545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define XSUB 1 /* expanding ${} string */ 555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define XARGSEP 2 /* ifs0 between "$*" */ 565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define XARG 3 /* expanding $*, $@ */ 575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define XCOM 4 /* expanding $() */ 585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define XNULLSUB 5 /* "$@" when $# is 0 (don't generate word) */ 595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define XSUBMID 6 /* middle of expanding ${} */ 605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* States used for field splitting */ 6250012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes#define IFS_WORD 0 /* word has chars (or quotes except "$@") */ 635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define IFS_WS 1 /* have seen IFS white-space */ 645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define IFS_NWS 2 /* have seen IFS non-white-space */ 65966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes#define IFS_IWS 3 /* beginning of word, ignore IFS WS */ 6650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes#define IFS_QUOTE 4 /* beg.w/quote, become IFS_WORD unless "$@" */ 675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6823925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes#define STYPE_CHAR 0xFF 6923925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes#define STYPE_DBL 0x100 7023925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes#define STYPE_AT 0x200 7123925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes#define STYPE_SINGLE 0x2FF 7223925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes#define STYPE_MASK 0x300 7323925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes 745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int varsub(Expand *, const char *, const char *, int *, int *); 75c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int comsub(Expand *, const char *, int); 76811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstatic char *valsub(struct op *, Area *); 775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char *trimsub(char *, char *, int); 78c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic void glob(char *, XPtrV *, bool); 795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void globit(XString *, char **, char *, XPtrV *, int); 8050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughesstatic const char *maybe_expand_tilde(const char *, XString *, char **, bool); 815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_NOPWNAM 825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char *homedir(char *); 835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void alt_expand(XPtrV *, char *, char *, char *, int); 85737fdce098f804459a925438e48dd711c31bbc9eElliott Hughesstatic int utflen(const char *) MKSH_A_PURE; 865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void utfincptr(const char *, mksh_ari_t *); 875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* UTFMODE functions */ 8903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int 905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruutflen(const char *s) 915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t n; 935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (UTFMODE) { 955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru n = 0; 965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*s) { 975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s += utf_ptradj(s); 985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++n; 995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru n = strlen(s); 10203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 10303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (n > 2147483647) 10403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra n = 2147483647; 10503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return ((int)n); 1065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 1095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruutfincptr(const char *s, mksh_ari_t *lp) 1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *cp = s; 1125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((*lp)--) 1145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp += utf_ptradj(cp); 1155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *lp = cp - s; 1165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* compile and expand word */ 1195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 1205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusubstitute(const char *cp, int f) 1215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct source *s, *sold; 1235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sold = source; 1255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = pushs(SWSTR, ATEMP); 1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->start = s->str = cp; 1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source = s; 1285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (yylex(ONEWORD) != LWORD) 12977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes internal_errorf(Tbadsubst); 1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source = sold; 1315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(s, ATEMP); 1325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (evalstr(yylval.cp, f)); 1335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 1365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * expand arg-list 1375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar ** 1395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querueval(const char **ap, int f) 1405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPtrV w; 1425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*ap == NULL) { 1445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru union mksh_ccphack vap; 1455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vap.ro = ap; 1475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (vap.rw); 1485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPinit(w, 32); 15003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* space for shell name */ 15103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra XPput(w, NULL); 1525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*ap != NULL) 1535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru expand(*ap++, &w, f); 1545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(w, NULL); 1555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ((char **)XPclose(w) + 1); 1565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 1595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * expand string 1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 1625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruevalstr(const char *cp, int f) 1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPtrV w; 1655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *dp = null; 1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPinit(w, 1); 1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru expand(cp, &w, f); 1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (XPsize(w)) 1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = *XPptrv(w); 1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPfree(w); 1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (dp); 1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * expand string - return only one component 1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * used from iosetup to expand redirection files 1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruevalonestr(const char *cp, int f) 1815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPtrV w; 1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *rv; 1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPinit(w, 1); 1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru expand(cp, &w, f); 1875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (XPsize(w)) { 1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 0: 1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = null; 1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 1: 1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = (char *) *XPptrv(w); 1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 19577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes rv = evalstr(cp, f & ~DOGLOB); 1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPfree(w); 1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (rv); 2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 2015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* for nested substitution: ${var:=$var2} */ 2035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutypedef struct SubType { 2045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *var; /* variable for ${var..} */ 2055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct SubType *prev; /* old type */ 2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct SubType *next; /* poped type (to avoid re-allocating) */ 207966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes size_t base; /* start position of expanded word */ 2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru short stype; /* [=+-?%#] action after expanded word */ 2095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru short f; /* saved value of f (DOPAT, etc) */ 2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru uint8_t quotep; /* saved value of quote (for ${..[%#]..}) */ 2115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru uint8_t quotew; /* saved value of quote (for ${..[+-=]..}) */ 2125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} SubType; 2135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 215811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserexpand( 216811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* input word */ 217811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser const char *ccp, 218811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* output words */ 219811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser XPtrV *wp, 220811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* DO* flags */ 221811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int f) 2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 2235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c = 0; 224811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* expansion type */ 225811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int type; 226811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* quoted */ 227811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int quote = 0; 228811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* destination string and live pointer */ 229811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser XString ds; 230811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char *dp; 231811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* source */ 232811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser const char *sp; 233811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* second pass flags */ 234811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int fdo; 235811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* have word */ 236811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int word; 237811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* field splitting of parameter/command substitution */ 238811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int doblank; 239811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* expansion variables */ 24003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Expand x = { 2415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru NULL, { NULL }, NULL, 0 2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru }; 2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru SubType st_head, *st; 244811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* record number of trailing newlines in COMSUB */ 24503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int newlines = 0; 246c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bool saw_eq, make_magic; 24750012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes unsigned int tilde_ok; 2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t len; 249811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char *cp; 2505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 251811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (ccp == NULL) 2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru internal_errorf("expand(NULL)"); 2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* for alias, readonly, set, typeset commands */ 254811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if ((f & DOVACHECK) && is_wdvarassign(ccp)) { 25556b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes f &= ~(DOVACHECK | DOBLANK | DOGLOB | DOTILDE); 25650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes f |= DOASNTILDE | DOSCALAR; 2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FNOGLOB)) 2595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f &= ~DOGLOB; 2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FMARKDIRS)) 2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f |= DOMARKDIRS; 2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FBRACEEXPAND) && (f & DOGLOB)) 26303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra f |= DOBRACE; 2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 26503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* init destination string */ 26603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xinit(ds, dp, 128, ATEMP); 2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XBASE; 268811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser sp = ccp; 2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fdo = 0; 270c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser saw_eq = false; 27103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* must be 1/0 */ 27256b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes tilde_ok = (f & (DOTILDE | DOASNTILDE)) ? 1 : 0; 2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank = 0; 274c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser make_magic = false; 2755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru word = (f&DOBLANK) ? IFS_WS : IFS_WORD; 2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* clang doesn't know OSUBST comes before CSUBST */ 2775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memset(&st_head, 0, sizeof(st_head)); 2785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st = &st_head; 2795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 28003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (/* CONSTCOND */ 1) { 2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xcheck(ds, dp); 2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (type) { 28403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case XBASE: 28503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* original prefixed string */ 28623925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes c = ord(*sp++); 2875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (c) { 2885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case EOS: 2895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = 0; 2905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case CHAR: 29223925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes c = ord(*sp++); 2935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case QCHAR: 29503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* temporary quote */ 29603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra quote |= 2; 29723925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes c = ord(*sp++); 2985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case OQUOTE: 30096b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes if (word != IFS_WORD) 30150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_QUOTE; 3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 0; 3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quote = 1; 3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 3055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case CQUOTE: 30696b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes if (word == IFS_QUOTE) 30796b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes word = IFS_WORD; 3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quote = st->quotew; 3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 310a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes case COMASUB: 3115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case COMSUB: 312a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes case FUNASUB: 313c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case FUNSUB: 314811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case VALSUB: 3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 0; 3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f & DONTRUNCOMMAND) { 3175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru word = IFS_WORD; 318c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *dp++ = '$'; 319a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes switch (c) { 320a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes case COMASUB: 321a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes case COMSUB: 322a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes *dp++ = '('; 323dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ORD(')'); 324a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes break; 325a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes case FUNASUB: 326a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes case FUNSUB: 327a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes case VALSUB: 328a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes *dp++ = '{'; 329a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes *dp++ = c == VALSUB ? '|' : ' '; 330dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ORD('}'); 331a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes break; 332a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes } 3335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*sp != '\0') { 3345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xcheck(ds, dp); 3355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = *sp++; 3365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 337dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((unsigned int)c == ORD('}')) 338c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *dp++ = ';'; 339a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes *dp++ = c; 3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 341c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser type = comsub(&x, sp, c); 342811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (type != XBASE && (f & DOBLANK)) 3435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank++; 3445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp = strnul(sp) + 1; 3455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newlines = 0; 3465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 3485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case EXPRSUB: 3495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 0; 3505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f & DONTRUNCOMMAND) { 351737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes word = IFS_WORD; 3525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = '$'; *dp++ = '('; *dp++ = '('; 3535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*sp != '\0') { 3545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xcheck(ds, dp); 3555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = *sp++; 3565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = ')'; *dp++ = ')'; 3585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 3595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl v; 3605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru v.flag = DEFINED|ISSET|INTEGER; 36203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* not default */ 36303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra v.type = 10; 3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru v.name[0] = '\0'; 3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru v_evaluate(&v, substitute(sp, 0), 3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru KSH_UNWIND_ERROR, true); 3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp = strnul(sp) + 1; 368737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes x.str = str_val(&v); 369737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes type = XSUB; 370737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 371737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes doblank++; 3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 37403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case OSUBST: { 37503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* ${{#}var{:}[=+-?#%]word} */ 37603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*- 37703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * format is: 3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * OSUBST [{x] plain-variable-part \0 3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * compiled-word-part CSUBST [}x] 3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This is where all syntax checking gets done... 3815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 38203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip the { or x (}) */ 38303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const char *varname = ++sp; 3845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int stype; 3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int slen = 0; 3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 38703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip variable */ 38803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp = cstrchr(sp, '\0') + 1; 3895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = varsub(&x, varname, sp, &stype, &slen); 3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (type < 0) { 3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *beg, *end, *str; 3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind_substsyn: 39303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* restore sp */ 39403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp = varname - 2; 39577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes beg = wdcopy(sp, ATEMP); 39677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes end = (wdscan(cstrchr(sp, '\0') + 1, 39777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes CSUBST) - sp) + beg; 3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* ({) the } or x is already skipped */ 3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (end < wdscan(beg, EOS)) 4005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *end = EOS; 40177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes str = snptreef(NULL, 64, Tf_S, beg); 4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(beg, ATEMP); 40377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes errorf(Tf_sD_s, str, Tbadsubst); 4045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f & DOBLANK) 4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank++; 4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 0; 40850012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (word == IFS_QUOTE && type != XNULLSUB) 40950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_WORD; 41003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (type == XBASE) { 41103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* expand? */ 4125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!st->next) { 4135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru SubType *newst; 4145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newst = alloc(sizeof(SubType), ATEMP); 4165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newst->next = NULL; 4175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newst->prev = st; 4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st->next = newst; 4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st = st->next; 4215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st->stype = stype; 4225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st->base = Xsavepos(ds, dp); 4235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st->f = f; 42477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes if (x.var == vtemp) { 42577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes st->var = tempvar(vtemp->name); 426c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser st->var->flag &= ~INTEGER; 427c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* can't fail here */ 428c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser setstr(st->var, 429c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser str_val(x.var), 430c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser KSH_RETURN_ERROR | 0x4); 431c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else 432c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser st->var = x.var; 433c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st->quotew = st->quotep = quote; 4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* skip qualifier(s) */ 4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (stype) 4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp += slen; 43823925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes switch (stype & STYPE_SINGLE) { 439dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('#') | STYPE_AT: 44003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra x.str = shf_smprintf("%08X", 441737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes (unsigned int)hash(str_val(st->var))); 442c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser break; 443dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('Q') | STYPE_AT: { 444c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct shf shf; 445c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 446c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf); 447c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser print_value_quoted(&shf, str_val(st->var)); 448c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser x.str = shf_sclose(&shf); 44903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 45056b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes } 451dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('0'): { 4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *beg, *mid, *end, *stg; 4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru mksh_ari_t from = 0, num = -1, flen, finc = 0; 4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru beg = wdcopy(sp, ATEMP); 4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru mid = beg + (wdscan(sp, ADELIM) - sp); 4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stg = beg + (wdscan(sp, CSUBST) - sp); 4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru mid[-2] = EOS; 459dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if (ord(mid[-1]) == ORD(/*{*/ '}')) { 4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp += mid - beg - 1; 4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru end = NULL; 4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru end = mid + 4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (wdscan(mid, ADELIM) - mid); 465dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if (ord(end[-1]) != ORD(/*{*/ '}')) 466fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes /* more than max delimiters */ 4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto unwind_substsyn; 4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru end[-2] = EOS; 4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp += end - beg - 1; 4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 47103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra evaluate(substitute(stg = wdstrip(beg, 0), 0), 4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru &from, KSH_UNWIND_ERROR, true); 4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(stg, ATEMP); 4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (end) { 47503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra evaluate(substitute(stg = wdstrip(mid, 0), 0), 4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru &num, KSH_UNWIND_ERROR, true); 4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(stg, ATEMP); 4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(beg, ATEMP); 4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru beg = str_val(st->var); 4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flen = utflen(beg); 4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (from < 0) { 4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (-from < flen) 4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru finc = flen + from; 4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru finc = from < flen ? from : flen; 4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (UTFMODE) 4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru utfincptr(beg, &finc); 4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru beg += finc; 4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flen = utflen(beg); 4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (num < 0 || num > flen) 4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru num = flen; 4935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (UTFMODE) 4945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru utfincptr(beg, &num); 4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(x.str, beg, num, ATEMP); 4965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto do_CSUBST; 49756b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes } 498dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('/') | STYPE_AT: 499dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('/'): { 5005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *s, *p, *d, *sbeg, *end; 50177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes char *pat = NULL, *rrep = null; 502fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes char fpat = 0, *tpat1, *tpat2; 50377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes char *ws, *wpat, *wrep; 5045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 50577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes s = ws = wdcopy(sp, ATEMP); 5065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = s + (wdscan(sp, ADELIM) - sp); 5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d = s + (wdscan(sp, CSUBST) - sp); 5085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p[-2] = EOS; 509dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if (ord(p[-1]) == ORD(/*{*/ '}')) 5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d = NULL; 5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 5125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d[-2] = EOS; 5135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp += (d ? d : p) - s - 1; 51423925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes if (!(stype & STYPE_MASK) && 515fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes s[0] == CHAR && 51623925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes ctype(s[1], C_SUB2)) 517fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes fpat = s[1]; 51877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes wpat = s + (fpat ? 2 : 0); 51977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes wrep = d ? p : NULL; 52023925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes if (!(stype & STYPE_AT)) { 52177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes rrep = wrep ? evalstr(wrep, 52277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes DOTILDE | DOSCALAR) : 52377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes null; 52477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes } 5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 52677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes /* prepare string on which to work */ 52777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes strdupx(s, str_val(st->var), ATEMP); 52877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes sbeg = s; 52977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes again_search: 53077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes pat = evalstr(wpat, 53177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes DOTILDE | DOSCALAR | DOPAT); 53203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check for special cases */ 533fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (!*pat && !fpat) { 534fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes /* 535fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes * empty unanchored 536fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes * pattern => reject 537fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes */ 5385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto no_repl; 53903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 54023925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes if ((stype & STYPE_MASK) && 541fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes gmatchx(null, pat, false)) { 54203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 54396b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes * pattern matches empty 54496b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes * string => don't loop 54503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 54623925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes stype &= ~STYPE_MASK; 54703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 5485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* first see if we have any match at all */ 550dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if (ord(fpat) == ORD('#')) { 5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* anchor at the beginning */ 552fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes tpat1 = shf_smprintf("%s%c*", pat, MAGIC); 5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tpat2 = tpat1; 554dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes } else if (ord(fpat) == ORD('%')) { 5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* anchor at the end */ 556fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes tpat1 = shf_smprintf("%c*%s", MAGIC, pat); 557fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes tpat2 = pat; 5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* float */ 5605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tpat1 = shf_smprintf("%c*%s%c*", MAGIC, pat, MAGIC); 5615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tpat2 = tpat1 + 2; 5625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru again_repl: 56403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 56503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * this would not be necessary if gmatchx would return 5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the start and end values of a match found, like re* 5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 5685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!gmatchx(sbeg, tpat1, false)) 5695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto end_repl; 5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru end = strnul(s); 5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* now anchor the beginning of the match */ 572dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if (ord(fpat) != ORD('#')) 5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (sbeg <= end) { 5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (gmatchx(sbeg, tpat2, false)) 5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sbeg++; 5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* now anchor the end of the match */ 5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = end; 581dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if (ord(fpat) != ORD('%')) 5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (p >= sbeg) { 5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool gotmatch; 5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 585dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ord(*p); 58603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *p = '\0'; 587fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes gotmatch = tobool(gmatchx(sbeg, pat, false)); 5885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p = c; 5895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (gotmatch) 5905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p--; 5925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 59377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes strndupx(end, sbeg, p - sbeg, ATEMP); 59477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes record_match(end); 59577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes afree(end, ATEMP); 59623925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes if (stype & STYPE_AT) { 59777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes if (rrep != null) 59877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes afree(rrep, ATEMP); 59977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes rrep = wrep ? evalstr(wrep, 60077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes DOTILDE | DOSCALAR) : 60177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes null; 60277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes } 6035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(end, s, sbeg - s, ATEMP); 60477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes d = shf_smprintf(Tf_sss, end, rrep, p); 6055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(end, ATEMP); 6065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sbeg = d + (sbeg - s) + strlen(rrep); 6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(s, ATEMP); 6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = d; 60923925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes if (stype & STYPE_AT) { 61077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes afree(tpat1, ATEMP); 61177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes afree(pat, ATEMP); 61277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes goto again_search; 61323925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes } else if (stype & STYPE_DBL) 6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto again_repl; 6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru end_repl: 6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(tpat1, ATEMP); 6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru x.str = s; 6185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru no_repl: 6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(pat, ATEMP); 6205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (rrep != null) 6215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(rrep, ATEMP); 62277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes afree(ws, ATEMP); 6235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto do_CSUBST; 62456b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes } 625dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('#'): 626dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('%'): 627fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes /* ! DOBLANK,DOBRACE */ 628c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser f = (f & DONTRUNCOMMAND) | 629fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes DOPAT | DOTILDE | 630fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes DOTEMP | DOSCALAR; 631fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes tilde_ok = 1; 6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st->quotew = quote = 0; 63303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 63403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Prepend open pattern (so | 6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * in a trim will work as 6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * expected) 6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 63803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!Flag(FSH)) { 63903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = MAGIC; 640dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes *dp++ = ORD(0x80 | '@'); 64103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 643dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('='): 64403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 645a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes * Tilde expansion for string 646a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes * variables in POSIX mode is 647a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes * governed by Austinbug 351. 648a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes * In non-POSIX mode historic 649a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes * ksh behaviour (enable it!) 650a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes * us followed. 6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Not doing tilde expansion 6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * for integer variables is a 6535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * non-POSIX thing - makes 6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * sense though, since ~ is 6555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a arithmetic operator. 6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(x.var->flag & INTEGER)) 65856b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes f |= DOASNTILDE | DOTILDE; 659a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes f |= DOTEMP | DOSCALAR; 66003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 66103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * These will be done after the 6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * value has been assigned. 6635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 66403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra f &= ~(DOBLANK|DOGLOB|DOBRACE); 6655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 1; 6665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 667dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('?'): 668fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (*sp == CSUBST) 669fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes errorf("%s: parameter null or not set", 670fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes st->var->name); 6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f &= ~DOBLANK; 67203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra f |= DOTEMP; 6735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* FALLTHROUGH */ 6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 67550012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes /* '-' '+' '?' */ 67650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (quote) 67750012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_WORD; 67850012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes else if (dp == Xstring(ds, dp)) 67950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_IWS; 6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Enable tilde expansion */ 6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 1; 6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f |= DOTILDE; 6835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 6855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* skip word */ 6865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp += wdscan(sp, CSUBST) - sp; 6875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 68856b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes } 68903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case CSUBST: 69003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* only get here if expanding word */ 6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do_CSUBST: 69203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* ({) skip the } or x */ 69303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp++; 69403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* in case of ${unset:-} */ 69503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tilde_ok = 0; 6965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp = '\0'; 6975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quote = st->quotep; 6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f = st->f; 699737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank--; 70123925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes switch (st->stype & STYPE_SINGLE) { 702dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('#'): 703dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('%'): 70403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!Flag(FSH)) { 70503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Append end-pattern */ 70603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = MAGIC; 70703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = ')'; 70803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 70903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp = '\0'; 7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = Xrestpos(ds, dp, st->base); 71103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 71203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Must use st->var since calling 7135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * global would break things 7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * like x[i+=1]. 7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru x.str = trimsub(str_val(st->var), 7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp, st->stype); 718737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (x.str[0] != '\0') { 71950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_IWS; 7205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XSUB; 72150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes } else if (quote) { 72250012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_WORD; 72350012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes type = XSUB; 72450012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes } else { 72550012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (dp == Xstring(ds, dp)) 72650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_IWS; 72750012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes type = XNULLSUB; 72850012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes } 729737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank++; 7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st = st->prev; 7325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 733dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('='): 73403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 73503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Restore our position and substitute 7365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the value of st->var (may not be 7375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the assigned value in the presence 7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of integer/right-adj/etc attributes). 7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = Xrestpos(ds, dp, st->base); 74103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 74203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Must use st->var since calling 7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * global would cause with things 7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * like x[i+=1] to be evaluated twice. 7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 74603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 74703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Note: not exported by FEXPORT 7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * in AT&T ksh. 7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 75003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 75103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * XXX POSIX says readonly is only 7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * fatal for special builtins (setstr 7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * does readonly check). 7545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = strlen(dp) + 1; 7565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setstr(st->var, 7575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru debunk(alloc(len, ATEMP), 7585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp, len), KSH_UNWIND_ERROR); 7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru x.str = str_val(st->var); 7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XSUB; 761737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 7625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank++; 7635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st = st->prev; 76450012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS; 7655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 766dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('?'): 767fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes dp = Xrestpos(ds, dp, st->base); 7685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 76977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes errorf(Tf_sD_s, st->var->name, 770fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes debunk(dp, dp, strlen(dp) + 1)); 771fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes break; 772dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('0'): 773dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('/') | STYPE_AT: 774dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('/'): 775dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('#') | STYPE_AT: 776dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('Q') | STYPE_AT: 7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = Xrestpos(ds, dp, st->base); 7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XSUB; 77950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS; 780737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 7815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank++; 7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st = st->prev; 7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 78450012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes /* default: '-' '+' */ 7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st = st->prev; 7875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XBASE; 7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 79003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case OPAT: 79103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* open pattern: *(foo|bar) */ 7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Next char is the type of pattern */ 793c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser make_magic = true; 794dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ord(*sp++) | 0x80U; 7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 79703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case SPAT: 79803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* pattern separator (|) */ 799c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser make_magic = true; 800dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ORD('|'); 8015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 80303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case CPAT: 80403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* close pattern */ 805c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser make_magic = true; 806dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ORD(/*(*/ ')'); 8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case XNULLSUB: 81203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 81303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Special case for "$@" (and "${foo[@]}") - no 8145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * word is generated if $# is 0 (unless there is 8155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * other stuff inside the quotes). 8165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 8175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XBASE; 818737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) { 8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank--; 82050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (dp == Xstring(ds, dp) && word != IFS_WORD) 82150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_IWS; 8225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case XSUB: 8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case XSUBMID: 827dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((c = ord(*x.str++)) == 0) { 8285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XBASE; 829737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank--; 8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 8325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case XARGSEP: 8365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XARG; 8375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quote = 1; 838c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 8395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case XARG: 840dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((c = ord(*x.str++)) == '\0') { 84103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 84203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * force null words to be created so 84356b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes * set -- "" 2 ""; echo "$@" will do 8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the right thing 8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (quote && x.split) 8475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru word = IFS_WORD; 8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((x.str = *x.u.strv++) == NULL) { 8495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XBASE; 850737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 8515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank--; 8525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 8535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 85423925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes c = ord(ifs0); 85550012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if ((f & DOHEREDOC)) { 85650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes /* pseudo-field-split reliably */ 85750012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (c == 0) 858dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ORD(' '); 85950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes break; 86050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes } 86150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if ((f & DOSCALAR)) { 86250012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes /* do not field-split */ 86356b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes if (x.split) { 864dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ORD(' '); 86556b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes break; 86656b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes } 86750012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (c == 0) 86856b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes continue; 86956b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes } 8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == 0) { 8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (quote && !x.split) 8725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 87356b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes if (!quote && word == IFS_WS) 87456b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes continue; 875811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* this is so we don't terminate */ 876dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ORD(' '); 877811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* now force-emit a word */ 878811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser goto emit_word; 8795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (quote && x.split) { 8815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* terminate word for "$@" */ 8825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XARGSEP; 8835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quote = 0; 8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case XCOM: 889811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (x.u.shf == NULL) { 890811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* $(<...) failed */ 891811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser subst_exstat = 1; 892811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* fake EOF */ 89350012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes c = -1; 894811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } else if (newlines) { 895811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* spit out saved NLs */ 896dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ORD('\n'); 8975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru --newlines; 8985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 899a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes while ((c = shf_getc(x.u.shf)) == 0 || 900dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes cinttype(c, C_NL)) { 901a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes#ifdef MKSH_WITH_TEXTMODE 902dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if (c == ORD('\r')) { 903a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes c = shf_getc(x.u.shf); 904a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes switch (c) { 905dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('\n'): 906a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes break; 907a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes default: 908a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes shf_ungetc(c, x.u.shf); 909a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes /* FALLTHROUGH */ 910a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes case -1: 911dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ORD('\r'); 912a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes break; 913a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes } 914a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes } 915a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes#endif 916dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if (c == ORD('\n')) 917811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* save newlines */ 9185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newlines++; 919a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes } 92050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (newlines && c != -1) { 9215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_ungetc(c, x.u.shf); 922dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ORD('\n'); 9235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru --newlines; 9245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 92650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (c == -1) { 9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newlines = 0; 928811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (x.u.shf) 929811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shf_close(x.u.shf); 9305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (x.split) 9315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru subst_exstat = waitlast(); 9325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XBASE; 933737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 9345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank--; 9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 9365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 9385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* check for end of word or IFS separation */ 9415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == 0 || (!quote && (f & DOBLANK) && doblank && 9425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru !make_magic && ctype(c, C_IFS))) { 94303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*- 94403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * How words are broken up: 9455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * | value of c 9465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * word | ws nws 0 9475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * ----------------------------------- 9485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * IFS_WORD w/WS w/NWS w 94956b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes * IFS_WS -/WS -/NWS - 95056b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes * IFS_NWS -/NWS w/NWS - 951f7f795644b6b1016c35b09d88c52f427473b3baeElliott Hughes * IFS_IWS -/WS w/NWS - 9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (w means generate a word) 9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 95450012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if ((word == IFS_WORD) || (word == IFS_QUOTE) || (c && 955f7f795644b6b1016c35b09d88c52f427473b3baeElliott Hughes (word == IFS_IWS || word == IFS_NWS) && 956f7f795644b6b1016c35b09d88c52f427473b3baeElliott Hughes !ctype(c, C_IFSWS))) { 957811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser emit_word: 958fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (f & DOHERESTR) 959fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes *dp++ = '\n'; 9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = '\0'; 961811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser cp = Xclose(ds, dp); 96203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (fdo & DOBRACE) 9635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* also does globbing */ 964811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser alt_expand(wp, cp, cp, 965811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser cp + Xlength(ds, (dp - 1)), 9665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fdo | (f & DOMARKDIRS)); 9675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (fdo & DOGLOB) 968811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser glob(cp, wp, tobool(f & DOMARKDIRS)); 96903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else if ((f & DOPAT) || !(fdo & DOMAGIC)) 970811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser XPput(*wp, cp); 9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 972811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser XPput(*wp, debunk(cp, cp, 973811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser strlen(cp) + 1)); 9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fdo = 0; 975c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser saw_eq = false; 97656b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes /* must be 1/0 */ 97756b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes tilde_ok = (f & (DOTILDE | DOASNTILDE)) ? 1 : 0; 978c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (c == 0) 979c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return; 980c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser Xinit(ds, dp, 128, ATEMP); 981c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else if (c == 0) { 9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 983c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else if (type == XSUB && ctype(c, C_IFS) && 984c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser !ctype(c, C_IFSWS) && Xlength(ds, dp) == 0) { 985811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser *(cp = alloc(1, ATEMP)) = '\0'; 986811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser XPput(*wp, cp); 987c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser type = XSUBMID; 988c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (word != IFS_NWS) 9905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru word = ctype(c, C_IFSWS) ? IFS_WS : IFS_NWS; 9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (type == XSUB) { 9935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (word == IFS_NWS && 9945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xlength(ds, dp) == 0) { 995811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser *(cp = alloc(1, ATEMP)) = '\0'; 996811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser XPput(*wp, cp); 9975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XSUBMID; 9995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* age tilde_ok info - ~ code tests second bit */ 10025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok <<= 1; 10035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* mark any special second pass chars */ 10045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!quote) 100523925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes switch (ord(c)) { 1006dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('['): 1007dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('!'): 1008dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('-'): 1009dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD(']'): 101003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 101103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * For character classes - doesn't hurt 10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * to have magic !,-,]s outside of 10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * [...] expressions. 10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f & (DOPAT | DOGLOB)) { 101603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fdo |= DOMAGIC; 1017dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((unsigned int)c == ORD('[')) 10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fdo |= f & DOGLOB; 10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = MAGIC; 10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1022dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('*'): 1023dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('?'): 10245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f & (DOPAT | DOGLOB)) { 102503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fdo |= DOMAGIC | (f & DOGLOB); 10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = MAGIC; 10275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1029dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('{'): 1030dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('}'): 1031dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD(','): 103223925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes if ((f & DOBRACE) && 1033dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes (ord(c) == ORD('{' /*}*/) || 103403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (fdo & DOBRACE))) { 103503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fdo |= DOBRACE|DOMAGIC; 10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = MAGIC; 10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1039dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('='): 10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Note first unquoted = for ~ */ 1041fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (!(f & DOTEMP) && (!Flag(FPOSIX) || 1042fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes (f & DOASNTILDE)) && !saw_eq) { 1043c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser saw_eq = true; 10445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 1; 10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1047dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD(':'): 104803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* : */ 10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Note unquoted : for ~ */ 105003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!(f & DOTEMP) && (f & DOASNTILDE)) 10515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 1; 10525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1053dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('~'): 105403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 105503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * tilde_ok is reset whenever 10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * any of ' " $( $(( ${ } are seen. 10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Note that tilde_ok must be preserved 10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * through the sequence ${A=a=}~ 10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (type == XBASE && 106156b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes (f & (DOTILDE | DOASNTILDE)) && 10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (tilde_ok & 2)) { 1063811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser const char *tcp; 1064811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char *tdp = dp; 10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1066811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser tcp = maybe_expand_tilde(sp, 1067811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser &ds, &tdp, 106850012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes tobool(f & DOASNTILDE)); 1069811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (tcp) { 1070811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (dp != tdp) 10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru word = IFS_WORD; 1072811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser dp = tdp; 1073811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser sp = tcp; 10745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 10755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 10785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 108003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* undo temporary */ 108103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra quote &= ~2; 10825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (make_magic) { 1084c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser make_magic = false; 108503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fdo |= DOMAGIC | (f & DOGLOB); 10865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = MAGIC; 10875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (ISMAGIC(c)) { 108803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fdo |= DOMAGIC; 10895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = MAGIC; 10905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 109103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* save output char */ 109203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = c; 10935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru word = IFS_WORD; 10945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1098fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughesstatic bool 1099fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hugheshasnonempty(const char **strv) 1100fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes{ 1101fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes size_t i = 0; 1102fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes 1103fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes while (strv[i]) 1104fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (*strv[i++]) 1105fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes return (true); 1106fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes return (false); 1107fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes} 1108fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes 11095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 11105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Prepare to generate the string returned by ${} substitution. 11115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 11135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvarsub(Expand *xp, const char *sp, const char *word, 11145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int *stypep, /* becomes qualifier type */ 11155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int *slenp) /* " " len (=, :=, etc.) valid iff *stypep != 0 */ 11165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int state; /* next state: XBASE, XARG, XSUB, XNULLSUB */ 11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int stype; /* substitution type */ 112077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes int slen = 0; 11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *p; 11225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *vp; 11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool zero_ok = false; 11245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 112523925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes if ((stype = ord(sp[0])) == '\0') 112603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Bad variable name */ 11275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 11285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->var = NULL; 11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /*- 11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * ${#var}, string length (-U: characters, +U: octets) or array size 11335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * ${%var}, string width (-U: screen columns, +U: octets) 11345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 113523925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes c = ord(sp[1]); 1136dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((unsigned int)stype == ORD('%') && c == '\0') 11375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 113823925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes if (ctype(stype, C_SUB2) && c != '\0') { 11395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Can't have any modifiers for ${#...} or ${%...} */ 11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*word != CSUBST) 11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp++; 11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Check for size of array */ 1144dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ORD('*') || 1145dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes ord(p[1]) == ORD('@')) && ord(p[2]) == ORD(']')) { 11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int n = 0; 11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1148dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((unsigned int)stype != ORD('#')) 11495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 11505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp = global(arrayname(sp)); 11515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (vp->flag & (ISSET|ARRAY)) 11525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru zero_ok = true; 11535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; vp; vp = vp->u.array) 11545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (vp->flag & ISSET) 11555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru n++; 11565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = n; 1157dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes } else if ((unsigned int)c == ORD('*') || 1158dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes (unsigned int)c == ORD('@')) { 1159dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((unsigned int)stype != ORD('#')) 11605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 11615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = e->loc->argc; 11625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 11635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = str_val(global(sp)); 11645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru zero_ok = p != null; 1165dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((unsigned int)stype == ORD('#')) 11665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = utflen(p); 11675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* partial utf_mbswidth reimplementation */ 11695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *s = p; 11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned int wc; 11715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t len; 11725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int cw; 11735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = 0; 11755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*s) { 11765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!UTFMODE || (len = utf_mbtowc(&wc, 11775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s)) == (size_t)-1) 11785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* not UTFMODE or not UTF-8 */ 117923925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes wc = rtt2asc(*s++); 11805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 11815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* UTFMODE and UTF-8 */ 11825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s += len; 11835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* wc == char or wchar at s++ */ 11845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((cw = utf_wcwidth(wc)) == -1) { 11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 646, 8859-1, 10646 C0/C1 */ 11865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = -1; 11875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 11885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c += cw; 11905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FNOUNSET) && c == 0 && !zero_ok) 119477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes errorf(Tf_parm, sp); 119503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* unqualified variable/string substitution */ 119603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *stypep = 0; 119777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes xp->str = shf_smprintf(Tf_d, c); 119877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes return (XSUB); 119977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes } 1200dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((unsigned int)stype == ORD('!') && c != '\0' && *word == CSUBST) { 120177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes sp++; 1202dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ORD('*') || 1203dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes ord(p[1]) == ORD('@')) && ord(p[2]) == ORD(']')) { 1204dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes c = ORD('!'); 120577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes stype = 0; 120677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes goto arraynames; 120777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes } 120877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes xp->var = global(sp); 120977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes xp->str = p ? shf_smprintf("%s[%lu]", 121077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes xp->var->name, arrayindex(xp->var)) : xp->var->name; 121177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes *stypep = 0; 12125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (XSUB); 12135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Check for qualifiers in word part */ 12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stype = 0; 121723925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes c = word[slen + 0] == CHAR ? ord(word[slen + 1]) : 0; 1218dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((unsigned int)c == ORD(':')) { 12195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru slen += 2; 122023925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes stype = STYPE_DBL; 122123925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes c = word[slen + 0] == CHAR ? ord(word[slen + 1]) : 0; 12225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1223dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if (!stype && (unsigned int)c == ORD('/')) { 12245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru slen += 2; 12255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stype = c; 122623925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes if (word[slen] == ADELIM && 122723925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes ord(word[slen + 1]) == (unsigned int)c) { 12285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru slen += 2; 122923925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes stype |= STYPE_DBL; 12305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1231dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes } else if (stype == STYPE_DBL && ((unsigned int)c == ORD(' ') || 1232dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes (unsigned int)c == ORD('0'))) { 1233dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes stype |= ORD('0'); 123423925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes } else if (ctype(c, C_SUB1)) { 12355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru slen += 2; 12365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stype |= c; 123723925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes } else if (ctype(c, C_SUB2)) { 123803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Note: ksh88 allows :%, :%%, etc */ 12395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru slen += 2; 12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stype = c; 124123925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes if (word[slen + 0] == CHAR && 124223925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes ord(word[slen + 1]) == (unsigned int)c) { 124323925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes stype |= STYPE_DBL; 12445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru slen += 2; 12455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1246dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes } else if ((unsigned int)c == ORD('@')) { 124703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* @x where x is command char */ 124823925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes switch (c = ord(word[slen + 2]) == CHAR ? 124923925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes ord(word[slen + 3]) : 0) { 1250dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('#'): 1251dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('/'): 1252dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('Q'): 1253a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes break; 1254a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes default: 1255a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes return (-1); 125603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 125723925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes stype |= STYPE_AT | c; 1258a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes slen += 4; 125903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (stype) 126003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* : is not ok */ 12615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 12625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!stype && *word != CSUBST) 12635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 12645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 126523925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes c = ord(sp[0]); 1266dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((unsigned int)c == ORD('*') || (unsigned int)c == ORD('@')) { 126723925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes switch (stype & STYPE_SINGLE) { 1268811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* can't assign to a vector */ 1269dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('='): 1270811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* can't trim a vector (yet) */ 1271dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('%'): 1272dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('#'): 1273dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('?'): 1274dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('0'): 1275dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('/') | STYPE_AT: 1276dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('/'): 1277dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('#') | STYPE_AT: 1278dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('Q') | STYPE_AT: 12795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 12805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (e->loc->argc == 0) { 12825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->str = null; 12835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->var = global(sp); 1284dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes state = (unsigned int)c == ORD('@') ? XNULLSUB : XSUB; 12855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 12865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->u.strv = (const char **)e->loc->argv + 1; 12875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->str = *xp->u.strv++; 1288c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* $@ */ 1289dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes xp->split = tobool((unsigned int)c == ORD('@')); 12905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru state = XARG; 12915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 129203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* POSIX 2009? */ 129303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra zero_ok = true; 1294dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes } else if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ORD('*') || 1295dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes ord(p[1]) == ORD('@')) && ord(p[2]) == ORD(']')) { 129677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes XPtrV wv; 129777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes 129823925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes switch (stype & STYPE_SINGLE) { 129977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes /* can't assign to a vector */ 1300dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('='): 130177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes /* can't trim a vector (yet) */ 1302dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('%'): 1303dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('#'): 1304dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('?'): 1305dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('0'): 1306dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('/') | STYPE_AT: 1307dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('/'): 1308dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('#') | STYPE_AT: 1309dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('Q') | STYPE_AT: 131077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes return (-1); 131177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes } 131277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes c = 0; 131377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes arraynames: 131477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes XPinit(wv, 32); 131577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes vp = global(arrayname(sp)); 131677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes for (; vp; vp = vp->u.array) { 131777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes if (!(vp->flag&ISSET)) 131877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes continue; 1319dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes XPput(wv, (unsigned int)c == ORD('!') ? 1320dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes shf_smprintf(Tf_lu, arrayindex(vp)) : 132177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes str_val(vp)); 132277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes } 132377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes if (XPsize(wv) == 0) { 132477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes xp->str = null; 1325dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes state = ord(p[1]) == ORD('@') ? XNULLSUB : XSUB; 132677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes XPfree(wv); 13275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 132877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes XPput(wv, 0); 132977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes xp->u.strv = (const char **)XPptrv(wv); 133077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes xp->str = *xp->u.strv++; 133177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes /* ${foo[@]} */ 1332dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes xp->split = tobool(ord(p[1]) == ORD('@')); 133377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes state = XARG; 13345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 133577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes } else { 133677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes xp->var = global(sp); 133777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes xp->str = str_val(xp->var); 133877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes /* can't assign things like $! or $1 */ 1339dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if ((unsigned int)(stype & STYPE_SINGLE) == ORD('=') && 1340dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes !*xp->str && ctype(*sp, C_VAR1 | C_DIGIT)) 134177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes return (-1); 134277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes state = XSUB; 13435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 134523925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes c = stype & STYPE_CHAR; 13465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* test the compiler's code generator */ 134723925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes if ((!(stype & STYPE_AT) && (ctype(c, C_SUB2) || 134823925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes (((stype & STYPE_DBL) ? *xp->str == '\0' : xp->str == null) && 1349fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes (state != XARG || (ifs0 || xp->split ? 1350fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes (xp->u.strv[0] == NULL) : !hasnonempty(xp->u.strv))) ? 1351dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes ctype(c, C_EQUAL | C_MINUS | C_QUEST) : (unsigned int)c == ORD('+')))) || 1352dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes (unsigned int)stype == (ORD('0') | STYPE_DBL) || 1353dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes (unsigned int)stype == (ORD('#') | STYPE_AT) || 1354dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes (unsigned int)stype == (ORD('Q') | STYPE_AT) || 1355dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes (unsigned int)(stype & STYPE_CHAR) == ORD('/')) 135603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* expand word instead of variable value */ 135703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra state = XBASE; 13585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FNOUNSET) && xp->str == null && !zero_ok && 1359dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes (ctype(c, C_SUB2) || (state != XBASE && (unsigned int)c != ORD('+')))) 136077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes errorf(Tf_parm, sp); 136177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes *stypep = stype; 136277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes *slenp = slen; 13635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (state); 13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 13675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Run the command in $(...) and read its output. 13685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 1370a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescomsub(Expand *xp, const char *cp, int fn) 13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Source *s, *sold; 13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t; 13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct shf *shf; 1375a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes bool doalias = false; 137603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra uint8_t old_utfmode = UTFMODE; 13775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1378a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes switch (fn) { 1379a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes case COMASUB: 1380a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes fn = COMSUB; 1381a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes if (0) 1382a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes /* FALLTHROUGH */ 1383a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes case FUNASUB: 1384a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes fn = FUNSUB; 1385a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes doalias = true; 1386a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes } 1387a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes 13885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = pushs(SSTRING, ATEMP); 13895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->start = s->str = cp; 13905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sold = source; 1391a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes t = compile(s, true, doalias); 13925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(s, ATEMP); 13935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source = sold; 13945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1395c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser UTFMODE = old_utfmode; 1396c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 13975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t == NULL) 13985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (XBASE); 13995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1400c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* no waitlast() unless specifically enabled later */ 1401c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser xp->split = false; 1402c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1403c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (t->type == TCOM && 14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *t->args == NULL && *t->vars == NULL && t->ioact != NULL) { 140503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* $(<file) */ 14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct ioword *io = *t->ioact; 14075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *name; 14085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 140977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes switch (io->ioflag & IOTYPE) { 141077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes case IOREAD: 141177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes shf = shf_open(name = evalstr(io->ioname, DOTILDE), 141277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes O_RDONLY, 0, SHF_MAPHI | SHF_CLEXEC); 141377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes if (shf == NULL) 141477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes warningf(!Flag(FTALKING), Tf_sD_s_sD_s, 141577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes name, Tcant_open, "$(<...) input", 141677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes cstrerror(errno)); 141777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes break; 141877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes case IOHERE: 141977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes if (!herein(io, &name)) { 142077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes xp->str = name; 142177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes /* as $(…) requires, trim trailing newlines */ 142223925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes name = strnul(name); 142377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes while (name > xp->str && name[-1] == '\n') 142477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes --name; 142577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes *name = '\0'; 142677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes return (XSUB); 142777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes } 142877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes shf = NULL; 142977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes break; 143077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes default: 143177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes errorf(Tf_sD_s, T_funny_command, 143277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes snptreef(NULL, 32, Tft_R, io)); 143377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes } 1434c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else if (fn == FUNSUB) { 1435c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int ofd1; 1436c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct temp *tf = NULL; 1437c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1438811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* 1439811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * create a temporary file, open for reading and writing, 1440811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * with an shf open for reading (buffered) but yet unused 1441811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser */ 1442c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser maketemp(ATEMP, TT_FUNSUB, &tf); 1443c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!tf->shf) { 144477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes errorf(Tf_temp, 144577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes Tcreate, tf->tffn, cstrerror(errno)); 1446c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1447811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* extract shf from temporary file, unlink and free it */ 1448811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shf = tf->shf; 1449811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser unlink(tf->tffn); 1450811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser afree(tf, ATEMP); 1451811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* save stdout and let it point to the tempfile */ 1452c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ofd1 = savefd(1); 1453811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser ksh_dup2(shf_fileno(shf), 1, false); 1454c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* 1455c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * run tree, with output thrown into the tempfile, 1456c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * in a new function block 1457c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser */ 1458811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser valsub(t, NULL); 1459c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser subst_exstat = exstat & 0xFF; 1460811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* rewind the tempfile and restore regular stdout */ 1461811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser lseek(shf_fileno(shf), (off_t)0, SEEK_SET); 1462c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser restfd(1, ofd1); 1463811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } else if (fn == VALSUB) { 1464811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser xp->str = valsub(t, ATEMP); 1465811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser subst_exstat = exstat & 0xFF; 1466811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (XSUB); 14675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 14685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int ofd1, pv[2]; 1469c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 14705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru openpipe(pv); 14715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf = shf_fdopen(pv[0], SHF_RD, NULL); 14725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ofd1 = savefd(1); 14735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pv[1] != 1) { 14745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_dup2(pv[1], 1, false); 14755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(pv[1]); 14765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1477c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser execute(t, XXCOM | XPIPEO | XFORK, NULL); 14785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru restfd(1, ofd1); 14795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru startlast(); 148003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* waitlast() */ 1481c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser xp->split = true; 14825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->u.shf = shf; 14855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (XCOM); 14865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 14875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 14895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * perform #pattern and %pattern substitution in ${} 14905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 14915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char * 14925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutrimsub(char *str, char *pat, int how) 14935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 14945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *end = strnul(str); 14955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *p, c; 14965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 149723925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes switch (how & (STYPE_CHAR | STYPE_DBL)) { 1498dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('#'): 149903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* shortest match at beginning */ 15005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = str; p <= end; p += utf_ptradj(p)) { 15015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *p; *p = '\0'; 15025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (gmatchx(str, pat, false)) { 150377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes record_match(str); 15045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p = c; 15055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p); 15065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p = c; 15085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1510dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('#') | STYPE_DBL: 151103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* longest match at beginning */ 15125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = end; p >= str; p--) { 15135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *p; *p = '\0'; 15145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (gmatchx(str, pat, false)) { 151577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes record_match(str); 15165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p = c; 15175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p); 15185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p = c; 15205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1522dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('%'): 152303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* shortest match at end */ 15245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = end; 15255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (p >= str) { 15265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (gmatchx(p, pat, false)) 15275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto trimsub_match; 15285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (UTFMODE) { 15295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *op = p; 153023925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes while ((p-- > str) && ((rtt2asc(*p) & 0xC0) == 0x80)) 15315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 15325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p < str) || (p + utf_ptradj(p) != op)) 15335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = op - 1; 15345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 15355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru --p; 15365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1538dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes case ORD('%') | STYPE_DBL: 153903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* longest match at end */ 15405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = str; p <= end; p++) 15415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (gmatchx(p, pat, false)) { 15425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru trimsub_match: 154377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes record_match(p); 15445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(end, str, p - str, ATEMP); 15455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (end); 15465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 15485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 155003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* no match, return string */ 155103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (str); 15525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 15535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 15555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * glob 15565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Name derived from V6's /etc/glob, the program that expanded filenames. 15575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 15585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* XXX cp not const 'cause slashes are temporarily replaced with NULs... */ 15605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 1561c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserglob(char *cp, XPtrV *wp, bool markdirs) 15625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 15635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int oldsize = XPsize(*wp); 15645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (glob_str(cp, wp, markdirs) == 0) 15665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(*wp, debunk(cp, cp, strlen(cp) + 1)); 15675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 15685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru qsort(XPptrv(*wp) + oldsize, XPsize(*wp) - oldsize, 156923925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes sizeof(void *), ascpstrcmp); 15705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 15715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define GF_NONE 0 15735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define GF_EXCHECK BIT(0) /* do existence check on file */ 15745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define GF_GLOBBED BIT(1) /* some globbing has been done */ 15755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define GF_MARKDIR BIT(2) /* add trailing / to directories */ 15765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 157703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 157803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Apply file globbing to cp and store the matching files in wp. Returns 15795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the number of matches found. 15805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 15815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 1582c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserglob_str(char *cp, XPtrV *wp, bool markdirs) 15835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 15845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int oldsize = XPsize(*wp); 15855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XString xs; 15865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *xp; 15875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xinit(xs, xp, 256, ATEMP); 15895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru globit(&xs, &xp, cp, wp, markdirs ? GF_MARKDIR : GF_NONE); 15905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xfree(xs, xp); 15915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (XPsize(*wp) - oldsize); 15935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 15945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 15965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruglobit(XString *xs, /* dest string */ 15975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char **xpp, /* ptr to dest end */ 15985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *sp, /* source path */ 15995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPtrV *wp, /* output list */ 16005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int check) /* GF_* flags */ 16015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 16025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *np; /* next source component */ 16035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *xp = *xpp; 16045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *se; 16055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char odirsep; 16065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* This to allow long expansions to be interrupted */ 16085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru intrcheck(); 16095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 161003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (sp == NULL) { 161103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* end of source path */ 161203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 161303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * We only need to check if the file exists if a pattern 16145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is followed by a non-pattern (eg, foo*x/bar; no check 16155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is needed for foo* since the match must exist) or if 16165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * any patterns were expanded and the markdirs option is set. 16175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Symlinks make things a bit tricky... 16185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 16195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((check & GF_EXCHECK) || 16205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ((check & GF_MARKDIR) && (check & GF_GLOBBED))) { 1621811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#define stat_check() (stat_done ? stat_done : (stat_done = \ 1622811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser stat(Xstring(*xs, xp), &statb) < 0 ? -1 : 1)) 16235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct stat lstatb, statb; 1624811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* -1: failed, 1 ok, 0 not yet done */ 1625811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int stat_done = 0; 16265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1627c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (mksh_lstat(Xstring(*xs, xp), &lstatb) < 0) 16285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 162903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 163003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * special case for systems which strip trailing 16315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * slashes from regular files (eg, /etc/passwd/). 16325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * SunOS 4.1.3 does this... 16335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 16345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((check & GF_EXCHECK) && xp > Xstring(*xs, xp) && 1635966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes mksh_cdirsep(xp[-1]) && !S_ISDIR(lstatb.st_mode) && 16365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (!S_ISLNK(lstatb.st_mode) || 16375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stat_check() < 0 || !S_ISDIR(statb.st_mode))) 16385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 163903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 164003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Possibly tack on a trailing / if there isn't already 16415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * one and if the file is a directory or a symlink to a 16425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * directory 16435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 16445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (((check & GF_MARKDIR) && (check & GF_GLOBBED)) && 1645966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes xp > Xstring(*xs, xp) && !mksh_cdirsep(xp[-1]) && 16465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (S_ISDIR(lstatb.st_mode) || 16475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (S_ISLNK(lstatb.st_mode) && stat_check() > 0 && 16485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru S_ISDIR(statb.st_mode)))) { 16495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xp++ = '/'; 16505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xp = '\0'; 16515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(np, Xstring(*xs, xp), Xlength(*xs, xp), ATEMP); 16545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(*wp, np); 16555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 16565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (xp > Xstring(*xs, xp)) 16595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xp++ = '/'; 1660966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes while (mksh_cdirsep(*sp)) { 16615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xcheck(*xs, xp); 16625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xp++ = *sp++; 16635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1664966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes np = mksh_sdirsep(sp); 16655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (np != NULL) { 16665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru se = np; 166703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* don't assume '/', can be multiple kinds */ 166803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra odirsep = *np; 16695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *np++ = '\0'; 16705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 16715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru odirsep = '\0'; /* keep gcc quiet */ 167223925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes se = strnul(sp); 16735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 167603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 167703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Check if sp needs globbing - done to avoid pattern checks for strings 16785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * containing MAGIC characters, open [s without the matching close ], 16795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * etc. (otherwise opendir() will be called which may fail because the 16805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * directory isn't readable - if no globbing is needed, only execute 16815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * permission should be required (as per POSIX)). 16825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 168323925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes if (!has_globbing(sp)) { 16845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(*xs, xp, se - sp + 1); 16855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru debunk(xp, sp, Xnleft(*xs, xp)); 168623925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes xp = strnul(xp); 16875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xpp = xp; 16885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru globit(xs, xpp, np, wp, check); 16895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 16905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru DIR *dirp; 16915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct dirent *d; 16925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *name; 169303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len, prefix_len; 16945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* xp = *xpp; copy_non_glob() may have re-alloc'd xs */ 16965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xp = '\0'; 16975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru prefix_len = Xlength(*xs, xp); 169877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes dirp = opendir(prefix_len ? Xstring(*xs, xp) : Tdot); 16995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (dirp == NULL) 17005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Nodir; 17015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((d = readdir(dirp)) != NULL) { 17025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru name = d->d_name; 17035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (name[0] == '.' && 17045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (name[1] == 0 || (name[1] == '.' && name[2] == 0))) 170503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* always ignore . and .. */ 170603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra continue; 17075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((*name == '.' && *sp != '.') || 17085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru !gmatchx(name, sp, true)) 17095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 17105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = strlen(d->d_name) + 1; 17125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(*xs, xp, len); 17135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(xp, name, len); 17145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xpp = xp + len - 1; 171523925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes globit(xs, xpp, np, wp, (check & GF_MARKDIR) | 171623925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes GF_GLOBBED | (np ? GF_EXCHECK : GF_NONE)); 17175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp = Xstring(*xs, xp) + prefix_len; 17185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru closedir(dirp); 17205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Nodir: 17215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 17225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (np != NULL) 17255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *--np = odirsep; 17265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 17275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* remove MAGIC from string */ 17295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 17305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudebunk(char *dp, const char *sp, size_t dlen) 17315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 17325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *d; 17335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *s; 17345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((s = cstrchr(sp, MAGIC))) { 17365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (s - sp >= (ssize_t)dlen) 17375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (dp); 17385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memmove(dp, sp, s - sp); 17395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (d = dp + (s - sp); *s && (d - dp < (ssize_t)dlen); s++) 17405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!ISMAGIC(*s) || !(*++s & 0x80) || 174123925bb36e72ff98ab562ea647e93db914e833d3Elliott Hughes !ctype(*s & 0x7F, C_PATMO | C_SPC)) 17425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *d++ = *s; 17435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 17445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* extended pattern operators: *+?@! */ 17455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((*s & 0x7f) != ' ') 17465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *d++ = *s & 0x7f; 17475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (d - dp < (ssize_t)dlen) 17485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *d++ = '('; 17495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *d = '\0'; 17515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (dp != sp) 17525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strlcpy(dp, sp, dlen); 17535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (dp); 17545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 17555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 175603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 175703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Check if p is an unquoted name, possibly followed by a / or :. If so 17585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * puts the expanded version in *dcp,dp and returns a pointer in p just 17595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * past the name, otherwise returns 0. 17605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 17615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char * 176250012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughesmaybe_expand_tilde(const char *p, XString *dsp, char **dpp, bool isassign) 17635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 17645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XString ts; 17655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *dp = *dpp; 17665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *tp; 17675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *r; 17685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xinit(ts, tp, 16, ATEMP); 17705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* : only for DOASNTILDE form */ 1771a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes while (p[0] == CHAR && /* not cdirsep */ p[1] != '/' && 1772966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes (!isassign || p[1] != ':')) { 17735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xcheck(ts, tp); 17745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *tp++ = p[1]; 17755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p += 2; 17765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *tp = '\0'; 17785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru r = (p[0] == EOS || p[0] == CHAR || p[0] == CSUBST) ? 177950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes do_tilde(Xstring(ts, tp)) : NULL; 17805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xfree(ts, tp); 17815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (r) { 17825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*r) { 17835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xcheck(*dsp, dp); 17845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(*r)) 17855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = MAGIC; 17865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = *r++; 17875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dpp = dp; 17895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru r = p; 17905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (r); 17925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 17935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 17955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * tilde expansion 17965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 17975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * based on a version by Arnold Robbins 17985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1799c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserchar * 180050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughesdo_tilde(char *cp) 18015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 18025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *dp = null; 180377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes#ifndef MKSH_NOPWNAM 180477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes bool do_simplify = true; 180577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes#endif 18065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 18075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (cp[0] == '\0') 18085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = str_val(global("HOME")); 18095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (cp[0] == '+' && cp[1] == '\0') 181077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes dp = str_val(global(TPWD)); 181196b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes else if (ksh_isdash(cp)) 181277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes dp = str_val(global(TOLDPWD)); 18135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_NOPWNAM 181477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes else { 18155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = homedir(cp); 181677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes do_simplify = false; 181777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes } 18185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 181977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes 182077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes /* if parameters aren't set, don't expand ~ */ 182177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes if (dp == NULL || dp == null) 182277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes return (NULL); 182377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes 182477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes /* simplify parameters as if cwd upon entry */ 182577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes#ifndef MKSH_NOPWNAM 182677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes if (do_simplify) 182777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes#endif 182877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes { 182977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes strdupx(dp, dp, ATEMP); 183077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes simplify_path(dp); 183177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes } 183277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes return (dp); 18335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 18345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 18355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_NOPWNAM 18365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 18375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * map userid to user's home directory. 18385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * note that 4.3's getpw adds more than 6K to the shell, 18395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * and the YP version probably adds much more. 18405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * we might consider our own version of getpwnam() to keep the size down. 18415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 18425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char * 18435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhomedir(char *name) 18445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 18455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *ap; 18465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 18475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ap = ktenter(&homedirs, name, hash(name)); 18485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(ap->flag & ISSET)) { 18495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct passwd *pw; 18505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 18515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pw = getpwnam(name); 18525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pw == NULL) 18535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 18545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strdupx(ap->val.s, pw->pw_dir, APERM); 18555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ap->flag |= DEFINED|ISSET|ALLOC; 18565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (ap->val.s); 18585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 18595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 18605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 18615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 18625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querualt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo) 18635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 186450012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes unsigned int count = 0; 18655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *brace_start, *brace_end, *comma = NULL; 18665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *field_start; 186750012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes char *p = exp_start; 18685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 18695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* search for open brace */ 1870dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes while ((p = strchr(p, MAGIC)) && ord(p[1]) != ORD('{' /*}*/)) 187150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes p += 2; 18725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru brace_start = p; 18735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 18745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* find matching close brace, if any */ 18755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p) { 18765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru comma = NULL; 18775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru count = 1; 187850012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes p += 2; 187950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes while (*p && count) { 188050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (ISMAGIC(*p++)) { 1881dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if (ord(*p) == ORD('{' /*}*/)) 188250012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes ++count; 1883dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes else if (ord(*p) == ORD(/*{*/ '}')) 18845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru --count; 18855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (*p == ',' && count == 1) 18865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru comma = p; 188750012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes ++p; 18885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* no valid expansions... */ 18925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!p || count != 0) { 189303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 189403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Note that given a{{b,c} we do not expand anything (this is 18955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * what AT&T ksh does. This may be changed to do the {b,c} 18965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * expansion. } 18975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 18985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (fdo & DOGLOB) 1899c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser glob(start, wp, tobool(fdo & DOMARKDIRS)); 19005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 19015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(*wp, debunk(start, start, end - start)); 19025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 19035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 19045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru brace_end = p; 19055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!comma) { 19065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru alt_expand(wp, start, brace_end, end, fdo); 19075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 19085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 19095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* expand expression */ 19115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru field_start = brace_start + 2; 19125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru count = 1; 19135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = brace_start + 2; p != brace_end; p++) { 19145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(*p)) { 1915dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes if (ord(*++p) == ORD('{' /*}*/)) 191650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes ++count; 1917dd4abe0a6aa4badb34480972d393466bf0e4c66bElliott Hughes else if ((ord(*p) == ORD(/*{*/ '}') && --count == 0) || 19185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*p == ',' && count == 1)) { 19195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *news; 19205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int l1, l2, l3; 19215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 192203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 192303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * addition safe since these operate on 192403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * one string (separate substrings) 192503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 19265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru l1 = brace_start - start; 19275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru l2 = (p - 1) - field_start; 19285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru l3 = end - brace_end; 19295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru news = alloc(l1 + l2 + l3 + 1, ATEMP); 19305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(news, start, l1); 19315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(news + l1, field_start, l2); 19325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(news + l1 + l2, brace_end, l3); 19335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru news[l1 + l2 + l3] = '\0'; 19345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru alt_expand(wp, news, news + l1, 19355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru news + l1 + l2 + l3, fdo); 19365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru field_start = p + 1; 19375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 19385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 19395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 19405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 19415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1942c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1943c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* helper function due to setjmp/longjmp woes */ 1944811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstatic char * 1945811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaservalsub(struct op *t, Area *ap) 1946c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{ 1947811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char * volatile cp = NULL; 1948811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser struct tbl * volatile vp = NULL; 1949811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1950811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser newenv(E_FUNC); 1951c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser newblock(); 1952811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (ap) 1953811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser vp = local("REPLY", false); 1954c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!kshsetjmp(e->jbuf)) 1955c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser execute(t, XXCOM | XERROK, NULL); 1956811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (vp) 1957811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser strdupx(cp, str_val(vp), ap); 1958811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser quitenv(NULL); 1959811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1960811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (cp); 1961c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser} 1962