X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Feval.c;fp=src%2Feval.c;h=f9c189d2782d984debebe32704707f935aacdf5d;hb=50012061ca3ad8e8a7f88c72130a5e22d797897e;hp=49a4c33e23dc184093961f3680b8576a19d9ec3e;hpb=948ca12d46512a832fe53ee24fd580e7addaf28d;p=android-x86%2Fexternal-mksh.git diff --git a/src/eval.c b/src/eval.c index 49a4c33..f9c189d 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2,7 +2,7 @@ /*- * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - * 2011, 2012, 2013, 2014 + * 2011, 2012, 2013, 2014, 2015 * Thorsten Glaser * * Provided that these terms and disclaimer and all copyright notices @@ -23,7 +23,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.153 2014/10/07 15:22:16 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.158.2.4 2015/03/01 15:42:58 tg Exp $"); /* * string expansion @@ -59,10 +59,11 @@ typedef struct { #define XSUBMID 6 /* middle of expanding ${} */ /* States used for field splitting */ -#define IFS_WORD 0 /* word has chars (or quotes) */ +#define IFS_WORD 0 /* word has chars (or quotes except "$@") */ #define IFS_WS 1 /* have seen IFS white-space */ #define IFS_NWS 2 /* have seen IFS non-white-space */ #define IFS_IWS 3 /* begin of word, ignore IFS WS */ +#define IFS_QUOTE 4 /* beg.w/quote, become IFS_WORD unless "$@" */ static int varsub(Expand *, const char *, const char *, int *, int *); static int comsub(Expand *, const char *, int); @@ -70,7 +71,7 @@ static char *valsub(struct op *, Area *); static char *trimsub(char *, char *, int); static void glob(char *, XPtrV *, bool); static void globit(XString *, char **, char *, XPtrV *, int); -static const char *maybe_expand_tilde(const char *, XString *, char **, int); +static const char *maybe_expand_tilde(const char *, XString *, char **, bool); #ifndef MKSH_NOPWNAM static char *homedir(char *); #endif @@ -237,7 +238,7 @@ expand( /* record number of trailing newlines in COMSUB */ int newlines = 0; bool saw_eq, make_magic; - int tilde_ok; + unsigned int tilde_ok; size_t len; char *cp; @@ -246,7 +247,7 @@ expand( /* for alias, readonly, set, typeset commands */ if ((f & DOVACHECK) && is_wdvarassign(ccp)) { f &= ~(DOVACHECK | DOBLANK | DOGLOB | DOTILDE); - f |= DOASNTILDE | DOASNFIELD; + f |= DOASNTILDE | DOSCALAR; } if (Flag(FNOGLOB)) f &= ~DOGLOB; @@ -290,7 +291,17 @@ expand( c = *sp++; break; case OQUOTE: - word = IFS_WORD; + switch (word) { + case IFS_QUOTE: + /* """something */ + word = IFS_WORD; + break; + case IFS_WORD: + break; + default: + word = IFS_QUOTE; + break; + } tilde_ok = 0; quote = 1; continue; @@ -383,6 +394,8 @@ expand( if (f & DOBLANK) doblank++; tilde_ok = 0; + if (word == IFS_QUOTE && type != XNULLSUB) + word = IFS_WORD; if (type == XBASE) { /* expand? */ if (!st->next) { @@ -516,7 +529,6 @@ expand( /* check for special cases */ d = str_val(st->var); - mkssert(d != NULL); switch (*pat) { case '#': /* anchor at begin */ @@ -622,7 +634,7 @@ expand( case '%': /* ! DOBLANK,DOBRACE,DOTILDE */ f = (f & DONTRUNCOMMAND) | - DOPAT | DOTEMP; + DOPAT | DOTEMP | DOSCALAR; st->quotew = quote = 0; /* * Prepend open pattern (so | @@ -631,7 +643,7 @@ expand( */ if (!Flag(FSH)) { *dp++ = MAGIC; - *dp++ = '@' | 0x80; + *dp++ = 0x80 | '@'; } break; case '=': @@ -664,7 +676,11 @@ expand( f |= DOTEMP; /* FALLTHROUGH */ default: - word = quote ? IFS_WORD : IFS_IWS; + /* '-' '+' '?' */ + if (quote) + word = IFS_WORD; + else if (dp == Xstring(ds, dp)) + word = IFS_IWS; /* Enable tilde expansion */ tilde_ok = 1; f |= DOTILDE; @@ -704,10 +720,16 @@ expand( x.str = trimsub(str_val(st->var), dp, st->stype); if (x.str[0] != '\0') { - word = IFS_WS; + word = IFS_IWS; type = XSUB; - } else - type = quote ? XSUB : XNULLSUB; + } else if (quote) { + word = IFS_WORD; + type = XSUB; + } else { + if (dp == Xstring(ds, dp)) + word = IFS_IWS; + type = XNULLSUB; + } if (f & DOBLANK) doblank++; st = st->prev; @@ -743,7 +765,7 @@ expand( if (f & DOBLANK) doblank++; st = st->prev; - word = quote || (!*x.str && (f & DOASNFIELD)) ? IFS_WORD : IFS_WS; + word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS; continue; case '?': { char *s = Xrestpos(ds, dp, st->base); @@ -759,11 +781,12 @@ expand( case 0x100 | 'Q': dp = Xrestpos(ds, dp, st->base); type = XSUB; - word = quote || (!*x.str && (f & DOASNFIELD)) ? IFS_WORD : IFS_WS; + word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS; if (f & DOBLANK) doblank++; st = st->prev; continue; + /* default: '-' '+' */ } st = st->prev; type = XBASE; @@ -799,8 +822,8 @@ expand( type = XBASE; if (f & DOBLANK) { doblank--; - if (dp == Xstring(ds, dp)) - word = IFS_WS; + if (dp == Xstring(ds, dp) && word != IFS_WORD) + word = IFS_IWS; } continue; @@ -834,15 +857,20 @@ expand( continue; } c = ifs0; - if ((f & DOASNFIELD)) { - /* assignment, do not field-split */ + if ((f & DOHEREDOC)) { + /* pseudo-field-split reliably */ + if (c == 0) + c = ' '; + break; + } + if ((f & DOSCALAR)) { + /* do not field-split */ if (x.split) { c = ' '; break; } - if (c == 0) { + if (c == 0) continue; - } } if (c == 0) { if (quote && !x.split) @@ -867,7 +895,7 @@ expand( /* $(<...) failed */ subst_exstat = 1; /* fake EOF */ - c = EOF; + c = -1; } else if (newlines) { /* spit out saved NLs */ c = '\n'; @@ -877,13 +905,13 @@ expand( if (c == '\n') /* save newlines */ newlines++; - if (newlines && c != EOF) { + if (newlines && c != -1) { shf_ungetc(c, x.u.shf); c = '\n'; --newlines; } } - if (c == EOF) { + if (c == -1) { newlines = 0; if (x.u.shf) shf_close(x.u.shf); @@ -911,7 +939,7 @@ expand( * IFS_IWS -/WS w/NWS - * (w means generate a word) */ - if ((word == IFS_WORD) || (c && + if ((word == IFS_WORD) || (word == IFS_QUOTE) || (c && (word == IFS_IWS || word == IFS_NWS) && !ctype(c, C_IFSWS))) { emit_word: @@ -1023,7 +1051,7 @@ expand( tcp = maybe_expand_tilde(sp, &ds, &tdp, - f & DOASNTILDE); + tobool(f & DOASNTILDE)); if (tcp) { if (dp != tdp) word = IFS_WORD; @@ -1659,7 +1687,7 @@ debunk(char *dp, const char *sp, size_t dlen) * past the name, otherwise returns 0. */ static const char * -maybe_expand_tilde(const char *p, XString *dsp, char **dpp, int isassign) +maybe_expand_tilde(const char *p, XString *dsp, char **dpp, bool isassign) { XString ts; char *dp = *dpp; @@ -1676,7 +1704,7 @@ maybe_expand_tilde(const char *p, XString *dsp, char **dpp, int isassign) } *tp = '\0'; r = (p[0] == EOS || p[0] == CHAR || p[0] == CSUBST) ? - tilde(Xstring(ts, tp)) : NULL; + do_tilde(Xstring(ts, tp)) : NULL; Xfree(ts, tp); if (r) { while (*r) { @@ -1698,7 +1726,7 @@ maybe_expand_tilde(const char *p, XString *dsp, char **dpp, int isassign) */ char * -tilde(char *cp) +do_tilde(char *cp) { char *dp = null; @@ -1745,28 +1773,30 @@ homedir(char *name) static void alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo) { - int count = 0; + unsigned int count = 0; char *brace_start, *brace_end, *comma = NULL; char *field_start; - char *p; + char *p = exp_start; /* search for open brace */ - for (p = exp_start; (p = strchr(p, MAGIC)) && p[1] != '{' /*}*/; p += 2) - ; + while ((p = strchr(p, MAGIC)) && p[1] != '{' /*}*/) + p += 2; brace_start = p; /* find matching close brace, if any */ if (p) { comma = NULL; count = 1; - for (p += 2; *p && count; p++) { - if (ISMAGIC(*p)) { - if (*++p == '{' /*}*/) - count++; + p += 2; + while (*p && count) { + if (ISMAGIC(*p++)) { + if (*p == '{' /*}*/) + ++count; else if (*p == /*{*/ '}') --count; else if (*p == ',' && count == 1) comma = p; + ++p; } } } @@ -1795,7 +1825,7 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo) for (p = brace_start + 2; p != brace_end; p++) { if (ISMAGIC(*p)) { if (*++p == '{' /*}*/) - count++; + ++count; else if ((*p == /*{*/ '}' && --count == 0) || (*p == ',' && count == 1)) { char *news;