eval.c revision fc0307d88e2ab13777f102dc63c0d1c968dc8bb2
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, 5fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes * 2011, 2012, 2013, 2014, 2015, 2016 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 26fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.180 2016/01/19 23:12:12 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 */ 65f7f795644b6b1016c35b09d88c52f427473b3baeElliott Hughes#define IFS_IWS 3 /* begin of word, ignore IFS WS */ 6650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes#define IFS_QUOTE 4 /* beg.w/quote, become IFS_WORD unless "$@" */ 675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int varsub(Expand *, const char *, const char *, int *, int *); 69c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int comsub(Expand *, const char *, int); 70811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstatic char *valsub(struct op *, Area *); 715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char *trimsub(char *, char *, int); 72c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic void glob(char *, XPtrV *, bool); 735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void globit(XString *, char **, char *, XPtrV *, int); 7450012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughesstatic const char *maybe_expand_tilde(const char *, XString *, char **, bool); 755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_NOPWNAM 765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char *homedir(char *); 775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void alt_expand(XPtrV *, char *, char *, char *, int); 79737fdce098f804459a925438e48dd711c31bbc9eElliott Hughesstatic int utflen(const char *) MKSH_A_PURE; 805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void utfincptr(const char *, mksh_ari_t *); 815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* UTFMODE functions */ 8303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int 845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruutflen(const char *s) 855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t n; 875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (UTFMODE) { 895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru n = 0; 905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*s) { 915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s += utf_ptradj(s); 925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++n; 935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru n = strlen(s); 9603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 9703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (n > 2147483647) 9803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra n = 2147483647; 9903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return ((int)n); 1005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 1035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruutfincptr(const char *s, mksh_ari_t *lp) 1045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *cp = s; 1065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((*lp)--) 1085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp += utf_ptradj(cp); 1095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *lp = cp - s; 1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* compile and expand word */ 1135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 1145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusubstitute(const char *cp, int f) 1155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct source *s, *sold; 1175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sold = source; 1195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = pushs(SWSTR, ATEMP); 1205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->start = s->str = cp; 1215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source = s; 1225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (yylex(ONEWORD) != LWORD) 12303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra internal_errorf("bad substitution"); 1245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source = sold; 1255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(s, ATEMP); 1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (evalstr(yylval.cp, f)); 1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * expand arg-list 1315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar ** 1335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querueval(const char **ap, int f) 1345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPtrV w; 1365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*ap == NULL) { 1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru union mksh_ccphack vap; 1395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vap.ro = ap; 1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (vap.rw); 1425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPinit(w, 32); 14403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* space for shell name */ 14503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra XPput(w, NULL); 1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*ap != NULL) 1475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru expand(*ap++, &w, f); 1485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(w, NULL); 1495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ((char **)XPclose(w) + 1); 1505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 1535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * expand string 1545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 1565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruevalstr(const char *cp, int f) 1575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPtrV w; 1595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *dp = null; 1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPinit(w, 1); 1625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru expand(cp, &w, f); 1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (XPsize(w)) 1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = *XPptrv(w); 1655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPfree(w); 1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (dp); 1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * expand string - return only one component 1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * used from iosetup to expand redirection files 1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruevalonestr(const char *cp, int f) 1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPtrV w; 1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *rv; 1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPinit(w, 1); 1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru expand(cp, &w, f); 1815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (XPsize(w)) { 1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 0: 1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = null; 1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 1: 1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = (char *) *XPptrv(w); 1875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = evalstr(cp, f&~DOGLOB); 1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPfree(w); 1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (rv); 1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* for nested substitution: ${var:=$var2} */ 1975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutypedef struct SubType { 1985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *var; /* variable for ${var..} */ 1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct SubType *prev; /* old type */ 2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct SubType *next; /* poped type (to avoid re-allocating) */ 201c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser size_t base; /* begin position of expanded word */ 2025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru short stype; /* [=+-?%#] action after expanded word */ 2035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru short f; /* saved value of f (DOPAT, etc) */ 2045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru uint8_t quotep; /* saved value of quote (for ${..[%#]..}) */ 2055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru uint8_t quotew; /* saved value of quote (for ${..[+-=]..}) */ 2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} SubType; 2075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 209811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserexpand( 210811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* input word */ 211811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser const char *ccp, 212811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* output words */ 213811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser XPtrV *wp, 214811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* DO* flags */ 215811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int f) 2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c = 0; 218811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* expansion type */ 219811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int type; 220811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* quoted */ 221811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int quote = 0; 222811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* destination string and live pointer */ 223811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser XString ds; 224811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char *dp; 225811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* source */ 226811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser const char *sp; 227811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* second pass flags */ 228811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int fdo; 229811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* have word */ 230811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int word; 231811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* field splitting of parameter/command substitution */ 232811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int doblank; 233811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* expansion variables */ 23403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Expand x = { 2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru NULL, { NULL }, NULL, 0 2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru }; 2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru SubType st_head, *st; 238811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* record number of trailing newlines in COMSUB */ 23903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int newlines = 0; 240c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bool saw_eq, make_magic; 24150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes unsigned int tilde_ok; 2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t len; 243811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char *cp; 2445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 245811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (ccp == NULL) 2465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru internal_errorf("expand(NULL)"); 2475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* for alias, readonly, set, typeset commands */ 248811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if ((f & DOVACHECK) && is_wdvarassign(ccp)) { 24956b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes f &= ~(DOVACHECK | DOBLANK | DOGLOB | DOTILDE); 25050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes f |= DOASNTILDE | DOSCALAR; 2515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FNOGLOB)) 2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f &= ~DOGLOB; 2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FMARKDIRS)) 2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f |= DOMARKDIRS; 2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FBRACEEXPAND) && (f & DOGLOB)) 25703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra f |= DOBRACE; 2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 25903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* init destination string */ 26003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xinit(ds, dp, 128, ATEMP); 2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XBASE; 262811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser sp = ccp; 2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fdo = 0; 264c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser saw_eq = false; 26503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* must be 1/0 */ 26656b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes tilde_ok = (f & (DOTILDE | DOASNTILDE)) ? 1 : 0; 2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank = 0; 268c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser make_magic = false; 2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru word = (f&DOBLANK) ? IFS_WS : IFS_WORD; 2705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* clang doesn't know OSUBST comes before CSUBST */ 2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memset(&st_head, 0, sizeof(st_head)); 2725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st = &st_head; 2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 27403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (/* CONSTCOND */ 1) { 2755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xcheck(ds, dp); 2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (type) { 27803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case XBASE: 27903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* original prefixed string */ 2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *sp++; 2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (c) { 2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case EOS: 2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = 0; 2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case CHAR: 2865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *sp++; 2875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case QCHAR: 28903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* temporary quote */ 29003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra quote |= 2; 2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *sp++; 2925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case OQUOTE: 29496b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes if (word != IFS_WORD) 29550012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_QUOTE; 2965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 0; 2975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quote = 1; 2985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case CQUOTE: 30096b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes if (word == IFS_QUOTE) 30196b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes word = IFS_WORD; 3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quote = st->quotew; 3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case COMSUB: 305c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case FUNSUB: 306811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case VALSUB: 3075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 0; 3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f & DONTRUNCOMMAND) { 3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru word = IFS_WORD; 310c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *dp++ = '$'; 311811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser *dp++ = c == COMSUB ? '(' : '{'; 312811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (c != COMSUB) 313811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser *dp++ = c == FUNSUB ? ' ' : '|'; 3145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*sp != '\0') { 3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xcheck(ds, dp); 3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = *sp++; 3175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 318811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (c != COMSUB) { 319c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *dp++ = ';'; 320c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *dp++ = '}'; 321c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else 322c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *dp++ = ')'; 3235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 324c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser type = comsub(&x, sp, c); 325811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (type != XBASE && (f & DOBLANK)) 3265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank++; 3275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp = strnul(sp) + 1; 3285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newlines = 0; 3295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 3315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case EXPRSUB: 3325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 0; 3335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f & DONTRUNCOMMAND) { 334737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes word = IFS_WORD; 3355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = '$'; *dp++ = '('; *dp++ = '('; 3365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*sp != '\0') { 3375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xcheck(ds, dp); 3385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = *sp++; 3395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = ')'; *dp++ = ')'; 3415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 3425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl v; 3435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru v.flag = DEFINED|ISSET|INTEGER; 34503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* not default */ 34603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra v.type = 10; 3475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru v.name[0] = '\0'; 3485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru v_evaluate(&v, substitute(sp, 0), 3495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru KSH_UNWIND_ERROR, true); 3505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp = strnul(sp) + 1; 351737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes x.str = str_val(&v); 352737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes type = XSUB; 353737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 354737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes doblank++; 3555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 35703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case OSUBST: { 35803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* ${{#}var{:}[=+-?#%]word} */ 35903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*- 36003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * format is: 3615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * OSUBST [{x] plain-variable-part \0 3625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * compiled-word-part CSUBST [}x] 3635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This is where all syntax checking gets done... 3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 36503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip the { or x (}) */ 36603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const char *varname = ++sp; 3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int stype; 3685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int slen = 0; 3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 37003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip variable */ 37103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp = cstrchr(sp, '\0') + 1; 3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = varsub(&x, varname, sp, &stype, &slen); 3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (type < 0) { 3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *beg, *end, *str; 3755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind_substsyn: 37603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* restore sp */ 37703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp = varname - 2; 3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru end = (beg = wdcopy(sp, ATEMP)) + 3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (wdscan(sp, CSUBST) - sp); 3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* ({) the } or x is already skipped */ 3815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (end < wdscan(beg, EOS)) 3825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *end = EOS; 3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru str = snptreef(NULL, 64, "%S", beg); 3845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(beg, ATEMP); 38503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s", str, "bad substitution"); 3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f & DOBLANK) 3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank++; 3895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 0; 39050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (word == IFS_QUOTE && type != XNULLSUB) 39150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_WORD; 39203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (type == XBASE) { 39303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* expand? */ 3945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!st->next) { 3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru SubType *newst; 3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newst = alloc(sizeof(SubType), ATEMP); 3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newst->next = NULL; 3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newst->prev = st; 4005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st->next = newst; 4015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st = st->next; 4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st->stype = stype; 4045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st->base = Xsavepos(ds, dp); 4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st->f = f; 406c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (x.var == &vtemp) { 407c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser st->var = tempvar(); 408c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser st->var->flag &= ~INTEGER; 409c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* can't fail here */ 410c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser setstr(st->var, 411c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser str_val(x.var), 412c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser KSH_RETURN_ERROR | 0x4); 413c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else 414c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser st->var = x.var; 415c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 4165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st->quotew = st->quotep = quote; 4175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* skip qualifier(s) */ 4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (stype) 4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp += slen; 42003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch (stype & 0x17F) { 421737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes case 0x100 | '#': 42203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra x.str = shf_smprintf("%08X", 423737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes (unsigned int)hash(str_val(st->var))); 424c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser break; 425811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case 0x100 | 'Q': { 426c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct shf shf; 427c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 428c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf); 429c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser print_value_quoted(&shf, str_val(st->var)); 430c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser x.str = shf_sclose(&shf); 43103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 43256b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes } 4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '0': { 4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *beg, *mid, *end, *stg; 4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru mksh_ari_t from = 0, num = -1, flen, finc = 0; 4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru beg = wdcopy(sp, ATEMP); 4385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru mid = beg + (wdscan(sp, ADELIM) - sp); 4395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stg = beg + (wdscan(sp, CSUBST) - sp); 4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru mid[-2] = EOS; 4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (mid[-1] == /*{*/'}') { 4425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp += mid - beg - 1; 4435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru end = NULL; 4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru end = mid + 4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (wdscan(mid, ADELIM) - mid); 447fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (end[-1] != /*{*/ '}') 448fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes /* more than max delimiters */ 4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto unwind_substsyn; 4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru end[-2] = EOS; 4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp += end - beg - 1; 4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 45303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra evaluate(substitute(stg = wdstrip(beg, 0), 0), 4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru &from, KSH_UNWIND_ERROR, true); 4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(stg, ATEMP); 4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (end) { 45703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra evaluate(substitute(stg = wdstrip(mid, 0), 0), 4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru &num, KSH_UNWIND_ERROR, true); 4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(stg, ATEMP); 4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(beg, ATEMP); 4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru beg = str_val(st->var); 4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flen = utflen(beg); 4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (from < 0) { 4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (-from < flen) 4665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru finc = flen + from; 4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru finc = from < flen ? from : flen; 4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (UTFMODE) 4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru utfincptr(beg, &finc); 4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru beg += finc; 4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flen = utflen(beg); 4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (num < 0 || num > flen) 4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru num = flen; 4755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (UTFMODE) 4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru utfincptr(beg, &num); 4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(x.str, beg, num, ATEMP); 4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto do_CSUBST; 47956b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes } 4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '/': { 4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *s, *p, *d, *sbeg, *end; 4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *pat, *rrep; 483fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes char fpat = 0, *tpat1, *tpat2; 4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = wdcopy(sp, ATEMP); 4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = s + (wdscan(sp, ADELIM) - sp); 4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d = s + (wdscan(sp, CSUBST) - sp); 4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p[-2] = EOS; 4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p[-1] == /*{*/'}') 4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d = NULL; 4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d[-2] = EOS; 4935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp += (d ? d : p) - s - 1; 494fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (!(stype & 0x80) && 495fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes s[0] == CHAR && 496fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes (s[1] == '#' || s[1] == '%')) 497fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes fpat = s[1]; 498fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes pat = evalstr(s + (fpat ? 2 : 0), 499fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes DOTILDE | DOSCALAR | DOPAT); 500fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes rrep = d ? evalstr(p, 501fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes DOTILDE | DOSCALAR) : null; 5025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(s, ATEMP); 5035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 50403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check for special cases */ 505fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (!*pat && !fpat) { 506fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes /* 507fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes * empty unanchored 508fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes * pattern => reject 509fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes */ 5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto no_repl; 51103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 512fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if ((stype & 0x80) && 513fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes gmatchx(null, pat, false)) { 51403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 51596b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes * pattern matches empty 51696b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes * string => don't loop 51703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 51896b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes stype &= ~0x80; 51903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* prepare string on which to work */ 52296b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes strdupx(s, str_val(st->var), ATEMP); 5235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sbeg = s; 5245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* first see if we have any match at all */ 526fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (fpat == '#') { 5275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* anchor at the beginning */ 528fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes tpat1 = shf_smprintf("%s%c*", pat, MAGIC); 5295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tpat2 = tpat1; 530fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes } else if (fpat == '%') { 5315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* anchor at the end */ 532fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes tpat1 = shf_smprintf("%c*%s", MAGIC, pat); 533fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes tpat2 = pat; 5345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 5355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* float */ 5365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tpat1 = shf_smprintf("%c*%s%c*", MAGIC, pat, MAGIC); 5375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tpat2 = tpat1 + 2; 5385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru again_repl: 54003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 54103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * this would not be necessary if gmatchx would return 5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the start and end values of a match found, like re* 5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!gmatchx(sbeg, tpat1, false)) 5455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto end_repl; 5465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru end = strnul(s); 5475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* now anchor the beginning of the match */ 548fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (fpat != '#') 5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (sbeg <= end) { 5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (gmatchx(sbeg, tpat2, false)) 5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sbeg++; 5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* now anchor the end of the match */ 5565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = end; 557fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (fpat != '%') 5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (p >= sbeg) { 5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool gotmatch; 5605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 56103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c = *p; 56203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *p = '\0'; 563fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes gotmatch = tobool(gmatchx(sbeg, pat, false)); 5645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p = c; 5655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (gotmatch) 5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p--; 5685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(end, s, sbeg - s, ATEMP); 5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d = shf_smprintf("%s%s%s", end, rrep, p); 5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(end, ATEMP); 5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sbeg = d + (sbeg - s) + strlen(rrep); 5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(s, ATEMP); 5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = d; 5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (stype & 0x80) 5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto again_repl; 5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru end_repl: 5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(tpat1, ATEMP); 5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru x.str = s; 5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru no_repl: 5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(pat, ATEMP); 5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (rrep != null) 5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(rrep, ATEMP); 5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto do_CSUBST; 58556b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes } 5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '#': 5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '%': 588fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes /* ! DOBLANK,DOBRACE */ 589c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser f = (f & DONTRUNCOMMAND) | 590fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes DOPAT | DOTILDE | 591fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes DOTEMP | DOSCALAR; 592fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes tilde_ok = 1; 5935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st->quotew = quote = 0; 59403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 59503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Prepend open pattern (so | 5965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * in a trim will work as 5975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * expected) 5985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 59903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!Flag(FSH)) { 60003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = MAGIC; 60150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes *dp++ = 0x80 | '@'; 60203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 6035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 6045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '=': 60503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 60603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Enabling tilde expansion 6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * after :s here is 6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * non-standard ksh, but is 6095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * consistent with rules for 6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * other assignments. Not 6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * sure what POSIX thinks of 6125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * this. 6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Not doing tilde expansion 6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * for integer variables is a 6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * non-POSIX thing - makes 6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * sense though, since ~ is 6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a arithmetic operator. 6185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(x.var->flag & INTEGER)) 62056b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes f |= DOASNTILDE | DOTILDE; 62103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra f |= DOTEMP; 62203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 62303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * These will be done after the 6245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * value has been assigned. 6255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 62603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra f &= ~(DOBLANK|DOGLOB|DOBRACE); 6275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 1; 6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '?': 630fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (*sp == CSUBST) 631fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes errorf("%s: parameter null or not set", 632fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes st->var->name); 6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f &= ~DOBLANK; 63403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra f |= DOTEMP; 6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* FALLTHROUGH */ 6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 63750012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes /* '-' '+' '?' */ 63850012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (quote) 63950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_WORD; 64050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes else if (dp == Xstring(ds, dp)) 64150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_IWS; 6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Enable tilde expansion */ 6435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 1; 6445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f |= DOTILDE; 6455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 6475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* skip word */ 6485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp += wdscan(sp, CSUBST) - sp; 6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 65056b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes } 65103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case CSUBST: 65203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* only get here if expanding word */ 6535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do_CSUBST: 65403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* ({) skip the } or x */ 65503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp++; 65603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* in case of ${unset:-} */ 65703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tilde_ok = 0; 6585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp = '\0'; 6595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quote = st->quotep; 6605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f = st->f; 661737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank--; 66303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch (st->stype & 0x17F) { 6645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '#': 6655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '%': 66603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!Flag(FSH)) { 66703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Append end-pattern */ 66803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = MAGIC; 66903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = ')'; 67003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 67103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp = '\0'; 6725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = Xrestpos(ds, dp, st->base); 67303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 67403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Must use st->var since calling 6755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * global would break things 6765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * like x[i+=1]. 6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru x.str = trimsub(str_val(st->var), 6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp, st->stype); 680737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (x.str[0] != '\0') { 68150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_IWS; 6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XSUB; 68350012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes } else if (quote) { 68450012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_WORD; 68550012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes type = XSUB; 68650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes } else { 68750012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (dp == Xstring(ds, dp)) 68850012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_IWS; 68950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes type = XNULLSUB; 69050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes } 691737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank++; 6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st = st->prev; 6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '=': 69603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 69703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Restore our position and substitute 6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the value of st->var (may not be 6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the assigned value in the presence 7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of integer/right-adj/etc attributes). 7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = Xrestpos(ds, dp, st->base); 70303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 70403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Must use st->var since calling 7055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * global would cause with things 7065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * like x[i+=1] to be evaluated twice. 7075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 70803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 70903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Note: not exported by FEXPORT 7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * in AT&T ksh. 7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 71203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 71303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * XXX POSIX says readonly is only 7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * fatal for special builtins (setstr 7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * does readonly check). 7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = strlen(dp) + 1; 7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setstr(st->var, 7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru debunk(alloc(len, ATEMP), 7205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp, len), KSH_UNWIND_ERROR); 7215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru x.str = str_val(st->var); 7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XSUB; 723737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank++; 7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st = st->prev; 72650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS; 7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 728fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes case '?': 729fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes dp = Xrestpos(ds, dp, st->base); 7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errorf("%s: %s", st->var->name, 732fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes debunk(dp, dp, strlen(dp) + 1)); 733fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes break; 7345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '0': 7355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '/': 73603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x100 | '#': 737c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case 0x100 | 'Q': 7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = Xrestpos(ds, dp, st->base); 7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XSUB; 74050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS; 741737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank++; 7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st = st->prev; 7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 74550012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes /* default: '-' '+' */ 7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru st = st->prev; 7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XBASE; 7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 7505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 75103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case OPAT: 75203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* open pattern: *(foo|bar) */ 7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Next char is the type of pattern */ 754c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser make_magic = true; 75503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c = *sp++ | 0x80; 7565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 75803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case SPAT: 75903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* pattern separator (|) */ 760c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser make_magic = true; 7615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = '|'; 7625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 76403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case CPAT: 76503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* close pattern */ 766c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser make_magic = true; 7675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = /*(*/ ')'; 7685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case XNULLSUB: 77303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 77403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Special case for "$@" (and "${foo[@]}") - no 7755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * word is generated if $# is 0 (unless there is 7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * other stuff inside the quotes). 7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XBASE; 779737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) { 7805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank--; 78150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (dp == Xstring(ds, dp) && word != IFS_WORD) 78250012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes word = IFS_IWS; 7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case XSUB: 7875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case XSUBMID: 7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((c = *x.str++) == 0) { 7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XBASE; 790737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 7915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank--; 7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 7935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case XARGSEP: 7975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XARG; 7985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quote = 1; 799c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 8005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case XARG: 8015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((c = *x.str++) == '\0') { 80203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 80303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * force null words to be created so 80456b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes * set -- "" 2 ""; echo "$@" will do 8055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the right thing 8065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (quote && x.split) 8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru word = IFS_WORD; 8095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((x.str = *x.u.strv++) == NULL) { 8105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XBASE; 811737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 8125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank--; 8135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 8145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = ifs0; 81650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if ((f & DOHEREDOC)) { 81750012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes /* pseudo-field-split reliably */ 81850012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (c == 0) 81950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes c = ' '; 82050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes break; 82150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes } 82250012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if ((f & DOSCALAR)) { 82350012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes /* do not field-split */ 82456b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes if (x.split) { 82556b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes c = ' '; 82656b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes break; 82756b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes } 82850012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (c == 0) 82956b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes continue; 83056b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes } 8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == 0) { 8325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (quote && !x.split) 8335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 83456b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes if (!quote && word == IFS_WS) 83556b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes continue; 836811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* this is so we don't terminate */ 8375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = ' '; 838811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* now force-emit a word */ 839811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser goto emit_word; 8405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (quote && x.split) { 8425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* terminate word for "$@" */ 8435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XARGSEP; 8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quote = 0; 8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case XCOM: 850811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (x.u.shf == NULL) { 851811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* $(<...) failed */ 852811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser subst_exstat = 1; 853811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* fake EOF */ 85450012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes c = -1; 855811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } else if (newlines) { 856811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* spit out saved NLs */ 8575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = '\n'; 8585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru --newlines; 8595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((c = shf_getc(x.u.shf)) == 0 || c == '\n') 8615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '\n') 862811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* save newlines */ 8635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newlines++; 86450012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (newlines && c != -1) { 8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_ungetc(c, x.u.shf); 8665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = '\n'; 8675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru --newlines; 8685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 87050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (c == -1) { 8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newlines = 0; 872811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (x.u.shf) 873811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shf_close(x.u.shf); 8745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (x.split) 8755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru subst_exstat = waitlast(); 8765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XBASE; 877737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (f & DOBLANK) 8785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru doblank--; 8795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* check for end of word or IFS separation */ 8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == 0 || (!quote && (f & DOBLANK) && doblank && 8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru !make_magic && ctype(c, C_IFS))) { 88703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*- 88803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * How words are broken up: 8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * | value of c 8905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * word | ws nws 0 8915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * ----------------------------------- 8925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * IFS_WORD w/WS w/NWS w 89356b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes * IFS_WS -/WS -/NWS - 89456b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes * IFS_NWS -/NWS w/NWS - 895f7f795644b6b1016c35b09d88c52f427473b3baeElliott Hughes * IFS_IWS -/WS w/NWS - 8965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (w means generate a word) 8975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 89850012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if ((word == IFS_WORD) || (word == IFS_QUOTE) || (c && 899f7f795644b6b1016c35b09d88c52f427473b3baeElliott Hughes (word == IFS_IWS || word == IFS_NWS) && 900f7f795644b6b1016c35b09d88c52f427473b3baeElliott Hughes !ctype(c, C_IFSWS))) { 901811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser emit_word: 902fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (f & DOHERESTR) 903fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes *dp++ = '\n'; 9045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = '\0'; 905811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser cp = Xclose(ds, dp); 90603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (fdo & DOBRACE) 9075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* also does globbing */ 908811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser alt_expand(wp, cp, cp, 909811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser cp + Xlength(ds, (dp - 1)), 9105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fdo | (f & DOMARKDIRS)); 9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (fdo & DOGLOB) 912811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser glob(cp, wp, tobool(f & DOMARKDIRS)); 91303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else if ((f & DOPAT) || !(fdo & DOMAGIC)) 914811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser XPput(*wp, cp); 9155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 916811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser XPput(*wp, debunk(cp, cp, 917811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser strlen(cp) + 1)); 9185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fdo = 0; 919c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser saw_eq = false; 92056b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes /* must be 1/0 */ 92156b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes tilde_ok = (f & (DOTILDE | DOASNTILDE)) ? 1 : 0; 922c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (c == 0) 923c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return; 924c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser Xinit(ds, dp, 128, ATEMP); 925c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else if (c == 0) { 9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 927c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else if (type == XSUB && ctype(c, C_IFS) && 928c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser !ctype(c, C_IFSWS) && Xlength(ds, dp) == 0) { 929811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser *(cp = alloc(1, ATEMP)) = '\0'; 930811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser XPput(*wp, cp); 931c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser type = XSUBMID; 932c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 9335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (word != IFS_NWS) 9345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru word = ctype(c, C_IFSWS) ? IFS_WS : IFS_NWS; 9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 9365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (type == XSUB) { 9375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (word == IFS_NWS && 9385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xlength(ds, dp) == 0) { 939811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser *(cp = alloc(1, ATEMP)) = '\0'; 940811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser XPput(*wp, cp); 9415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type = XSUBMID; 9435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* age tilde_ok info - ~ code tests second bit */ 9465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok <<= 1; 9475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* mark any special second pass chars */ 9485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!quote) 9495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (c) { 9505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '[': 951c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '!': 9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '-': 9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case ']': 95403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 95503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * For character classes - doesn't hurt 9565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * to have magic !,-,]s outside of 9575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * [...] expressions. 9585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 9595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f & (DOPAT | DOGLOB)) { 96003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fdo |= DOMAGIC; 9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '[') 9625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fdo |= f & DOGLOB; 9635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = MAGIC; 9645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 9665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '*': 9675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '?': 9685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f & (DOPAT | DOGLOB)) { 96903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fdo |= DOMAGIC | (f & DOGLOB); 9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = MAGIC; 9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 973c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '{': 974c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '}': 9755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case ',': 976c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((f & DOBRACE) && (c == '{' /*}*/ || 97703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (fdo & DOBRACE))) { 97803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fdo |= DOBRACE|DOMAGIC; 9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = MAGIC; 9805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '=': 9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Note first unquoted = for ~ */ 984fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (!(f & DOTEMP) && (!Flag(FPOSIX) || 985fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes (f & DOASNTILDE)) && !saw_eq) { 986c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser saw_eq = true; 9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 1; 9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 99003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case ':': 99103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* : */ 9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Note unquoted : for ~ */ 99303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!(f & DOTEMP) && (f & DOASNTILDE)) 9945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tilde_ok = 1; 9955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 9965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '~': 99703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 99803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * tilde_ok is reset whenever 9995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * any of ' " $( $(( ${ } are seen. 10005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Note that tilde_ok must be preserved 10015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * through the sequence ${A=a=}~ 10025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (type == XBASE && 100456b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes (f & (DOTILDE | DOASNTILDE)) && 10055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (tilde_ok & 2)) { 1006811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser const char *tcp; 1007811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char *tdp = dp; 10085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1009811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser tcp = maybe_expand_tilde(sp, 1010811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser &ds, &tdp, 101150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes tobool(f & DOASNTILDE)); 1012811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (tcp) { 1013811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (dp != tdp) 10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru word = IFS_WORD; 1015811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser dp = tdp; 1016811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser sp = tcp; 10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 102303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* undo temporary */ 102403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra quote &= ~2; 10255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (make_magic) { 1027c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser make_magic = false; 102803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fdo |= DOMAGIC | (f & DOGLOB); 10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = MAGIC; 10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (ISMAGIC(c)) { 103103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fdo |= DOMAGIC; 10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = MAGIC; 10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 103403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* save output char */ 103503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = c; 10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru word = IFS_WORD; 10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1041fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughesstatic bool 1042fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hugheshasnonempty(const char **strv) 1043fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes{ 1044fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes size_t i = 0; 1045fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes 1046fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes while (strv[i]) 1047fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes if (*strv[i++]) 1048fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes return (true); 1049fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes return (false); 1050fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes} 1051fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes 10525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 10535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Prepare to generate the string returned by ${} substitution. 10545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvarsub(Expand *xp, const char *sp, const char *word, 10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int *stypep, /* becomes qualifier type */ 10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int *slenp) /* " " len (=, :=, etc.) valid iff *stypep != 0 */ 10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int state; /* next state: XBASE, XARG, XSUB, XNULLSUB */ 10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int stype; /* substitution type */ 10635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int slen; 10645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *p; 10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *vp; 10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool zero_ok = false; 10675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 106803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((stype = sp[0]) == '\0') 106903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Bad variable name */ 10705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->var = NULL; 10735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /*- 10755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * ${#var}, string length (-U: characters, +U: octets) or array size 10765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * ${%var}, string width (-U: screen columns, +U: octets) 10775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = sp[1]; 10795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (stype == '%' && c == '\0') 10805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 10815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((stype == '#' || stype == '%') && c != '\0') { 10825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Can't have any modifiers for ${#...} or ${%...} */ 10835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*word != CSUBST) 10845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 10855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp++; 10865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Check for size of array */ 10875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p = cstrchr(sp, '[')) && (p[1] == '*' || p[1] == '@') && 10885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p[2] == ']') { 10895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int n = 0; 10905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (stype != '#') 10925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 10935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp = global(arrayname(sp)); 10945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (vp->flag & (ISSET|ARRAY)) 10955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru zero_ok = true; 10965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; vp; vp = vp->u.array) 10975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (vp->flag & ISSET) 10985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru n++; 10995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = n; 11005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (c == '*' || c == '@') { 11015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (stype != '#') 11025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 11035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = e->loc->argc; 11045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 11055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = str_val(global(sp)); 11065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru zero_ok = p != null; 11075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (stype == '#') 11085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = utflen(p); 11095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 11105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* partial utf_mbswidth reimplementation */ 11115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *s = p; 11125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned int wc; 11135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t len; 11145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int cw; 11155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = 0; 11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*s) { 11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!UTFMODE || (len = utf_mbtowc(&wc, 11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s)) == (size_t)-1) 11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* not UTFMODE or not UTF-8 */ 11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = (unsigned char)(*s++); 11225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* UTFMODE and UTF-8 */ 11245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s += len; 11255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* wc == char or wchar at s++ */ 11265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((cw = utf_wcwidth(wc)) == -1) { 11275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 646, 8859-1, 10646 C0/C1 */ 11285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = -1; 11295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c += cw; 11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FNOUNSET) && c == 0 && !zero_ok) 113603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s", sp, "parameter not set"); 113703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* unqualified variable/string substitution */ 113803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *stypep = 0; 11395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->str = shf_smprintf("%d", c); 11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (XSUB); 11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Check for qualifiers in word part */ 11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stype = 0; 11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = word[slen = 0] == CHAR ? word[1] : 0; 11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == ':') { 11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru slen += 2; 11485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stype = 0x80; 11495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = word[slen + 0] == CHAR ? word[slen + 1] : 0; 11505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!stype && c == '/') { 11525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru slen += 2; 11535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stype = c; 11545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (word[slen] == ADELIM) { 11555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru slen += 2; 11565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stype |= 0x80; 11575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (stype == 0x80 && (c == ' ' || c == '0')) { 11595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stype |= '0'; 11605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (ctype(c, C_SUBOP1)) { 11615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru slen += 2; 11625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stype |= c; 116303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (ctype(c, C_SUBOP2)) { 116403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Note: ksh88 allows :%, :%%, etc */ 11655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru slen += 2; 11665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stype = c; 11675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (word[slen + 0] == CHAR && c == word[slen + 1]) { 11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stype |= 0x80; 11695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru slen += 2; 11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 117103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (c == '@') { 117203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* @x where x is command char */ 117303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra slen += 2; 117403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra stype |= 0x100; 117503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (word[slen] == CHAR) { 117603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra stype |= word[slen + 1]; 117703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra slen += 2; 117803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 117903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (stype) 118003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* : is not ok */ 11815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 11825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!stype && *word != CSUBST) 11835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 11845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *stypep = stype; 11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *slenp = slen; 11865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = sp[0]; 11885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '*' || c == '@') { 118903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch (stype & 0x17F) { 1190811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* can't assign to a vector */ 1191811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case '=': 1192811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* can't trim a vector (yet) */ 1193811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case '%': 11945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '#': 11955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '0': 11965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '/': 119703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x100 | '#': 1198c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case 0x100 | 'Q': 11995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 12005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (e->loc->argc == 0) { 12025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->str = null; 12035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->var = global(sp); 12045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru state = c == '@' ? XNULLSUB : XSUB; 12055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 12065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->u.strv = (const char **)e->loc->argv + 1; 12075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->str = *xp->u.strv++; 1208c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* $@ */ 1209c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser xp->split = tobool(c == '@'); 12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru state = XARG; 12115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 121203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* POSIX 2009? */ 121303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra zero_ok = true; 12145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 12155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p = cstrchr(sp, '[')) && (p[1] == '*' || p[1] == '@') && 12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p[2] == ']') { 12175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPtrV wv; 12185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 121903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch (stype & 0x17F) { 1220811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* can't assign to a vector */ 1221811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case '=': 1222811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* can't trim a vector (yet) */ 1223811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case '%': 12245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '#': 12255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '?': 12265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '0': 12275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '/': 122803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x100 | '#': 1229c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case 0x100 | 'Q': 12305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 12315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPinit(wv, 32); 12335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((c = sp[0]) == '!') 12345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++sp; 12355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp = global(arrayname(sp)); 12365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; vp; vp = vp->u.array) { 12375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(vp->flag&ISSET)) 12385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 12395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(wv, c == '!' ? shf_smprintf("%lu", 12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru arrayindex(vp)) : 12415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru str_val(vp)); 12425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (XPsize(wv) == 0) { 12445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->str = null; 12455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru state = p[1] == '@' ? XNULLSUB : XSUB; 12465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPfree(wv); 12475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 12485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(wv, 0); 12495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->u.strv = (const char **)XPptrv(wv); 12505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->str = *xp->u.strv++; 1251c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* ${foo[@]} */ 1252c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser xp->split = tobool(p[1] == '@'); 12535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru state = XARG; 12545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 12565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Can't assign things like $! or $1 */ 125703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((stype & 0x17F) == '=' && 12585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ctype(*sp, C_VAR1 | C_DIGIT)) 12595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 12605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*sp == '!' && sp[1]) { 12615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++sp; 12625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->var = global(sp); 1263737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes if (vstrchr(sp, '[')) 1264737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes xp->str = shf_smprintf("%s[%lu]", 1265737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes xp->var->name, 1266737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes arrayindex(xp->var)); 12675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 1268737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes xp->str = xp->var->name; 12695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 12705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->var = global(sp); 12715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->str = str_val(xp->var); 12725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru state = XSUB; 12745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 127703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c = stype & 0x7F; 12785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* test the compiler's code generator */ 127903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (((stype < 0x100) && (ctype(c, C_SUBOP2) || c == '/' || 1280fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes (((stype & 0x80) ? *xp->str == '\0' : xp->str == null) && 1281fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes (state != XARG || (ifs0 || xp->split ? 1282fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes (xp->u.strv[0] == NULL) : !hasnonempty(xp->u.strv))) ? 128303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c == '=' || c == '-' || c == '?' : c == '+'))) || 1284c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser stype == (0x80 | '0') || stype == (0x100 | '#') || 1285c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser stype == (0x100 | 'Q')) 128603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* expand word instead of variable value */ 128703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra state = XBASE; 12885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FNOUNSET) && xp->str == null && !zero_ok && 12895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (ctype(c, C_SUBOP2) || (state != XBASE && c != '+'))) 129003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s", sp, "parameter not set"); 12915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (state); 12925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Run the command in $(...) and read its output. 12965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 12975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 1298c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasercomsub(Expand *xp, const char *cp, int fn MKSH_A_UNUSED) 12995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Source *s, *sold; 13015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t; 13025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct shf *shf; 130303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra uint8_t old_utfmode = UTFMODE; 13045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = pushs(SSTRING, ATEMP); 13065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->start = s->str = cp; 13075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sold = source; 130803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra t = compile(s, true); 13095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(s, ATEMP); 13105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source = sold; 13115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1312c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser UTFMODE = old_utfmode; 1313c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 13145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t == NULL) 13155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (XBASE); 13165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1317c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* no waitlast() unless specifically enabled later */ 1318c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser xp->split = false; 1319c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1320c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (t->type == TCOM && 13215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *t->args == NULL && *t->vars == NULL && t->ioact != NULL) { 132203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* $(<file) */ 13235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct ioword *io = *t->ioact; 13245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *name; 13255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1326b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes if ((io->ioflag & IOTYPE) != IOREAD) 1327fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes errorf("%s: %s", T_funny_command, 13285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru snptreef(NULL, 32, "%R", io)); 1329fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes shf = shf_open(name = evalstr(io->ioname, DOTILDE), O_RDONLY, 1330fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes 0, SHF_MAPHI | SHF_CLEXEC); 13315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (shf == NULL) 1332811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser warningf(!Flag(FTALKING), "%s: %s %s: %s", name, 1333811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser "can't open", "$(<...) input", cstrerror(errno)); 1334c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else if (fn == FUNSUB) { 1335c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int ofd1; 1336c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct temp *tf = NULL; 1337c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1338811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* 1339811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * create a temporary file, open for reading and writing, 1340811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * with an shf open for reading (buffered) but yet unused 1341811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser */ 1342c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser maketemp(ATEMP, TT_FUNSUB, &tf); 1343c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!tf->shf) { 1344c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser errorf("can't %s temporary file %s: %s", 1345c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser "create", tf->tffn, cstrerror(errno)); 1346c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1347811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* extract shf from temporary file, unlink and free it */ 1348811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shf = tf->shf; 1349811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser unlink(tf->tffn); 1350811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser afree(tf, ATEMP); 1351811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* save stdout and let it point to the tempfile */ 1352c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ofd1 = savefd(1); 1353811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser ksh_dup2(shf_fileno(shf), 1, false); 1354c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* 1355c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * run tree, with output thrown into the tempfile, 1356c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * in a new function block 1357c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser */ 1358811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser valsub(t, NULL); 1359c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser subst_exstat = exstat & 0xFF; 1360811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* rewind the tempfile and restore regular stdout */ 1361811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser lseek(shf_fileno(shf), (off_t)0, SEEK_SET); 1362c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser restfd(1, ofd1); 1363811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } else if (fn == VALSUB) { 1364811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser xp->str = valsub(t, ATEMP); 1365811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser subst_exstat = exstat & 0xFF; 1366811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (XSUB); 13675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 13685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int ofd1, pv[2]; 1369c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 13705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru openpipe(pv); 13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf = shf_fdopen(pv[0], SHF_RD, NULL); 13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ofd1 = savefd(1); 13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pv[1] != 1) { 13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_dup2(pv[1], 1, false); 13755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(pv[1]); 13765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1377c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser execute(t, XXCOM | XPIPEO | XFORK, NULL); 13785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru restfd(1, ofd1); 13795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru startlast(); 138003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* waitlast() */ 1381c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser xp->split = true; 13825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp->u.shf = shf; 13855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (XCOM); 13865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 13895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * perform #pattern and %pattern substitution in ${} 13905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char * 13925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutrimsub(char *str, char *pat, int how) 13935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *end = strnul(str); 13955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *p, c; 13965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (how & 0xFF) { 139803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '#': 139903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* shortest match at beginning */ 14005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = str; p <= end; p += utf_ptradj(p)) { 14015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *p; *p = '\0'; 14025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (gmatchx(str, pat, false)) { 14035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p = c; 14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p); 14055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p = c; 14075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 140903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '#'|0x80: 141003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* longest match at beginning */ 14115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = end; p >= str; p--) { 14125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *p; *p = '\0'; 14135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (gmatchx(str, pat, false)) { 14145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p = c; 14155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p); 14165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p = c; 14185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 142003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '%': 142103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* shortest match at end */ 14225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = end; 14235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (p >= str) { 14245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (gmatchx(p, pat, false)) 14255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto trimsub_match; 14265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (UTFMODE) { 14275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *op = p; 14285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((p-- > str) && ((*p & 0xC0) == 0x80)) 14295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 14305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p < str) || (p + utf_ptradj(p) != op)) 14315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = op - 1; 14325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 14335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru --p; 14345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 143603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '%'|0x80: 143703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* longest match at end */ 14385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = str; p <= end; p++) 14395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (gmatchx(p, pat, false)) { 14405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru trimsub_match: 14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(end, str, p - str, ATEMP); 14425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (end); 14435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 14455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 144703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* no match, return string */ 144803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (str); 14495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 14505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 14525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * glob 14535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Name derived from V6's /etc/glob, the program that expanded filenames. 14545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 14555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* XXX cp not const 'cause slashes are temporarily replaced with NULs... */ 14575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 1458c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserglob(char *cp, XPtrV *wp, bool markdirs) 14595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 14605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int oldsize = XPsize(*wp); 14615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (glob_str(cp, wp, markdirs) == 0) 14635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(*wp, debunk(cp, cp, strlen(cp) + 1)); 14645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 14655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru qsort(XPptrv(*wp) + oldsize, XPsize(*wp) - oldsize, 14665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sizeof(void *), xstrcmp); 14675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 14685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define GF_NONE 0 14705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define GF_EXCHECK BIT(0) /* do existence check on file */ 14715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define GF_GLOBBED BIT(1) /* some globbing has been done */ 14725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define GF_MARKDIR BIT(2) /* add trailing / to directories */ 14735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 147403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 147503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Apply file globbing to cp and store the matching files in wp. Returns 14765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the number of matches found. 14775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 14785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 1479c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserglob_str(char *cp, XPtrV *wp, bool markdirs) 14805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 14815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int oldsize = XPsize(*wp); 14825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XString xs; 14835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *xp; 14845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xinit(xs, xp, 256, ATEMP); 14865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru globit(&xs, &xp, cp, wp, markdirs ? GF_MARKDIR : GF_NONE); 14875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xfree(xs, xp); 14885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (XPsize(*wp) - oldsize); 14905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 14915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 14935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruglobit(XString *xs, /* dest string */ 14945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char **xpp, /* ptr to dest end */ 14955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *sp, /* source path */ 14965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPtrV *wp, /* output list */ 14975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int check) /* GF_* flags */ 14985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 14995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *np; /* next source component */ 15005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *xp = *xpp; 15015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *se; 15025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char odirsep; 15035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* This to allow long expansions to be interrupted */ 15055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru intrcheck(); 15065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 150703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (sp == NULL) { 150803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* end of source path */ 150903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 151003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * We only need to check if the file exists if a pattern 15115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is followed by a non-pattern (eg, foo*x/bar; no check 15125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is needed for foo* since the match must exist) or if 15135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * any patterns were expanded and the markdirs option is set. 15145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Symlinks make things a bit tricky... 15155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 15165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((check & GF_EXCHECK) || 15175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ((check & GF_MARKDIR) && (check & GF_GLOBBED))) { 1518811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#define stat_check() (stat_done ? stat_done : (stat_done = \ 1519811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser stat(Xstring(*xs, xp), &statb) < 0 ? -1 : 1)) 15205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct stat lstatb, statb; 1521811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* -1: failed, 1 ok, 0 not yet done */ 1522811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser int stat_done = 0; 15235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1524c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (mksh_lstat(Xstring(*xs, xp), &lstatb) < 0) 15255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 152603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 152703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * special case for systems which strip trailing 15285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * slashes from regular files (eg, /etc/passwd/). 15295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * SunOS 4.1.3 does this... 15305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 15315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((check & GF_EXCHECK) && xp > Xstring(*xs, xp) && 15325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp[-1] == '/' && !S_ISDIR(lstatb.st_mode) && 15335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (!S_ISLNK(lstatb.st_mode) || 15345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stat_check() < 0 || !S_ISDIR(statb.st_mode))) 15355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 153603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 153703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Possibly tack on a trailing / if there isn't already 15385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * one and if the file is a directory or a symlink to a 15395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * directory 15405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 15415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (((check & GF_MARKDIR) && (check & GF_GLOBBED)) && 15425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp > Xstring(*xs, xp) && xp[-1] != '/' && 15435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (S_ISDIR(lstatb.st_mode) || 15445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (S_ISLNK(lstatb.st_mode) && stat_check() > 0 && 15455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru S_ISDIR(statb.st_mode)))) { 15465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xp++ = '/'; 15475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xp = '\0'; 15485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(np, Xstring(*xs, xp), Xlength(*xs, xp), ATEMP); 15515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(*wp, np); 15525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 15535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (xp > Xstring(*xs, xp)) 15565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xp++ = '/'; 15575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*sp == '/') { 15585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xcheck(*xs, xp); 15595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xp++ = *sp++; 15605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru np = strchr(sp, '/'); 15625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (np != NULL) { 15635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru se = np; 156403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* don't assume '/', can be multiple kinds */ 156503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra odirsep = *np; 15665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *np++ = '\0'; 15675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 15685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru odirsep = '\0'; /* keep gcc quiet */ 15695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru se = sp + strlen(sp); 15705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 157303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 157403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Check if sp needs globbing - done to avoid pattern checks for strings 15755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * containing MAGIC characters, open [s without the matching close ], 15765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * etc. (otherwise opendir() will be called which may fail because the 15775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * directory isn't readable - if no globbing is needed, only execute 15785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * permission should be required (as per POSIX)). 15795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 15805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!has_globbing(sp, se)) { 15815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(*xs, xp, se - sp + 1); 15825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru debunk(xp, sp, Xnleft(*xs, xp)); 15835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp += strlen(xp); 15845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xpp = xp; 15855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru globit(xs, xpp, np, wp, check); 15865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 15875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru DIR *dirp; 15885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct dirent *d; 15895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *name; 159003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len, prefix_len; 15915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* xp = *xpp; copy_non_glob() may have re-alloc'd xs */ 15935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xp = '\0'; 15945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru prefix_len = Xlength(*xs, xp); 15955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dirp = opendir(prefix_len ? Xstring(*xs, xp) : "."); 15965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (dirp == NULL) 15975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Nodir; 15985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((d = readdir(dirp)) != NULL) { 15995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru name = d->d_name; 16005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (name[0] == '.' && 16015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (name[1] == 0 || (name[1] == '.' && name[2] == 0))) 160203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* always ignore . and .. */ 160303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra continue; 16045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((*name == '.' && *sp != '.') || 16055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru !gmatchx(name, sp, true)) 16065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 16075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = strlen(d->d_name) + 1; 16095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(*xs, xp, len); 16105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(xp, name, len); 16115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xpp = xp + len - 1; 16125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru globit(xs, xpp, np, wp, 16135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (check & GF_MARKDIR) | GF_GLOBBED 16145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru | (np ? GF_EXCHECK : GF_NONE)); 16155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp = Xstring(*xs, xp) + prefix_len; 16165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru closedir(dirp); 16185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Nodir: 16195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 16205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (np != NULL) 16235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *--np = odirsep; 16245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* remove MAGIC from string */ 16275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 16285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudebunk(char *dp, const char *sp, size_t dlen) 16295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 16305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *d; 16315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *s; 16325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((s = cstrchr(sp, MAGIC))) { 16345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (s - sp >= (ssize_t)dlen) 16355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (dp); 16365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memmove(dp, sp, s - sp); 16375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (d = dp + (s - sp); *s && (d - dp < (ssize_t)dlen); s++) 16385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!ISMAGIC(*s) || !(*++s & 0x80) || 16395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru !vstrchr("*+?@! ", *s & 0x7f)) 16405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *d++ = *s; 16415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 16425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* extended pattern operators: *+?@! */ 16435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((*s & 0x7f) != ' ') 16445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *d++ = *s & 0x7f; 16455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (d - dp < (ssize_t)dlen) 16465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *d++ = '('; 16475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *d = '\0'; 16495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (dp != sp) 16505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strlcpy(dp, sp, dlen); 16515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (dp); 16525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 165403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 165503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Check if p is an unquoted name, possibly followed by a / or :. If so 16565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * puts the expanded version in *dcp,dp and returns a pointer in p just 16575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * past the name, otherwise returns 0. 16585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 16595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char * 166050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughesmaybe_expand_tilde(const char *p, XString *dsp, char **dpp, bool isassign) 16615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 16625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XString ts; 16635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *dp = *dpp; 16645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *tp; 16655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *r; 16665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xinit(ts, tp, 16, ATEMP); 16685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* : only for DOASNTILDE form */ 16695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (p[0] == CHAR && p[1] != '/' && (!isassign || p[1] != ':')) 16705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { 16715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xcheck(ts, tp); 16725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *tp++ = p[1]; 16735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p += 2; 16745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *tp = '\0'; 16765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru r = (p[0] == EOS || p[0] == CHAR || p[0] == CSUBST) ? 167750012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes do_tilde(Xstring(ts, tp)) : NULL; 16785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xfree(ts, tp); 16795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (r) { 16805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*r) { 16815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xcheck(*dsp, dp); 16825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(*r)) 16835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = MAGIC; 16845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dp++ = *r++; 16855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dpp = dp; 16875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru r = p; 16885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (r); 16905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 16935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * tilde expansion 16945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 16955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * based on a version by Arnold Robbins 16965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 16975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1698c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserchar * 169950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughesdo_tilde(char *cp) 17005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 17015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *dp = null; 17025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (cp[0] == '\0') 17045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = str_val(global("HOME")); 17055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (cp[0] == '+' && cp[1] == '\0') 17065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = str_val(global("PWD")); 170796b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes else if (ksh_isdash(cp)) 17085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = str_val(global("OLDPWD")); 17095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_NOPWNAM 17105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 17115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = homedir(cp); 17125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 17135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* If HOME, PWD or OLDPWD are not set, don't expand ~ */ 17145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (dp == null ? NULL : dp); 17155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 17165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_NOPWNAM 17185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 17195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * map userid to user's home directory. 17205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * note that 4.3's getpw adds more than 6K to the shell, 17215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * and the YP version probably adds much more. 17225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * we might consider our own version of getpwnam() to keep the size down. 17235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 17245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char * 17255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhomedir(char *name) 17265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 17275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *ap; 17285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ap = ktenter(&homedirs, name, hash(name)); 17305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(ap->flag & ISSET)) { 17315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct passwd *pw; 17325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pw = getpwnam(name); 17345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pw == NULL) 17355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 17365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strdupx(ap->val.s, pw->pw_dir, APERM); 17375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ap->flag |= DEFINED|ISSET|ALLOC; 17385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (ap->val.s); 17405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 17415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 17425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 17445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querualt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo) 17455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 174650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes unsigned int count = 0; 17475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *brace_start, *brace_end, *comma = NULL; 17485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *field_start; 174950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes char *p = exp_start; 17505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* search for open brace */ 175250012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes while ((p = strchr(p, MAGIC)) && p[1] != '{' /*}*/) 175350012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes p += 2; 17545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru brace_start = p; 17555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* find matching close brace, if any */ 17575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p) { 17585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru comma = NULL; 17595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru count = 1; 176050012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes p += 2; 176150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes while (*p && count) { 176250012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (ISMAGIC(*p++)) { 176350012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes if (*p == '{' /*}*/) 176450012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes ++count; 1765c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser else if (*p == /*{*/ '}') 17665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru --count; 17675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (*p == ',' && count == 1) 17685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru comma = p; 176950012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes ++p; 17705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* no valid expansions... */ 17745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!p || count != 0) { 177503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 177603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Note that given a{{b,c} we do not expand anything (this is 17775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * what AT&T ksh does. This may be changed to do the {b,c} 17785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * expansion. } 17795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 17805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (fdo & DOGLOB) 1781c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser glob(start, wp, tobool(fdo & DOMARKDIRS)); 17825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 17835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XPput(*wp, debunk(start, start, end - start)); 17845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 17855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru brace_end = p; 17875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!comma) { 17885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru alt_expand(wp, start, brace_end, end, fdo); 17895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 17905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* expand expression */ 17935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru field_start = brace_start + 2; 17945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru count = 1; 17955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = brace_start + 2; p != brace_end; p++) { 17965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(*p)) { 1797c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (*++p == '{' /*}*/) 179850012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes ++count; 1799c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser else if ((*p == /*{*/ '}' && --count == 0) || 18005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*p == ',' && count == 1)) { 18015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *news; 18025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int l1, l2, l3; 18035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 180403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 180503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * addition safe since these operate on 180603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * one string (separate substrings) 180703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 18085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru l1 = brace_start - start; 18095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru l2 = (p - 1) - field_start; 18105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru l3 = end - brace_end; 18115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru news = alloc(l1 + l2 + l3 + 1, ATEMP); 18125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(news, start, l1); 18135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(news + l1, field_start, l2); 18145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(news + l1 + l2, brace_end, l3); 18155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru news[l1 + l2 + l3] = '\0'; 18165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru alt_expand(wp, news, news + l1, 18175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru news + l1 + l2 + l3, fdo); 18185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru field_start = p + 1; 18195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 18235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1824c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1825c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* helper function due to setjmp/longjmp woes */ 1826811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstatic char * 1827811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaservalsub(struct op *t, Area *ap) 1828c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{ 1829811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char * volatile cp = NULL; 1830811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser struct tbl * volatile vp = NULL; 1831811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1832811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser newenv(E_FUNC); 1833c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser newblock(); 1834811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (ap) 1835811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser vp = local("REPLY", false); 1836c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!kshsetjmp(e->jbuf)) 1837c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser execute(t, XXCOM | XERROK, NULL); 1838811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (vp) 1839811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser strdupx(cp, str_val(vp), ap); 1840811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser quitenv(NULL); 1841811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1842811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (cp); 1843c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser} 1844