diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 76172031b0b1..14396cf92d70 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -1,4 +1,4 @@ -/* $NetBSD: eval.c,v 1.77 2004/06/26 14:09:58 dsl Exp $ */ +/* $NetBSD: eval.c,v 1.78 2004/06/26 22:09:49 dsl Exp $ */ /*- * Copyright (c) 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; #else -__RCSID("$NetBSD: eval.c,v 1.77 2004/06/26 14:09:58 dsl Exp $"); +__RCSID("$NetBSD: eval.c,v 1.78 2004/06/26 22:09:49 dsl Exp $"); #endif #endif /* not lint */ @@ -354,7 +354,7 @@ evalfor(union node *n, int flags) setstackmark(&smark); arglist.lastp = &arglist.list; for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { - expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_IFS_SPLIT); + expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); if (evalskip) goto out; } @@ -702,6 +702,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) arglist.lastp = &arglist.list; varflag = 1; + /* Expand arguments, ignoring the initial 'name=value' ones */ for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { char *p = argp->narg.text; if (varflag && is_name(*p)) { @@ -718,6 +719,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) expredir(cmd->ncmd.redirect); + /* Now do the initial 'name=value' ones we skipped above */ varlist.lastp = &varlist.list; for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { char *p = argp->narg.text; diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 4cefa8b47411..924fc7e0f257 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -1,4 +1,4 @@ -/* $NetBSD: expand.c,v 1.65 2004/06/26 20:48:44 dsl Exp $ */ +/* $NetBSD: expand.c,v 1.66 2004/06/26 22:09:49 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95"; #else -__RCSID("$NetBSD: expand.c,v 1.65 2004/06/26 20:48:44 dsl Exp $"); +__RCSID("$NetBSD: expand.c,v 1.66 2004/06/26 22:09:49 dsl Exp $"); #endif #endif /* not lint */ @@ -175,9 +175,9 @@ expandarg(union node *arg, struct arglist *arglist, int flag) /* - * Perform variable and command substitution. If EXP_FULL is set, output CTLESC - * characters to allow for further processing. Otherwise treat - * $@ like $* since no splitting will be performed. + * Perform variable and command substitution. + * If EXP_FULL is set, output CTLESC characters to allow for further processing. + * Otherwise treat $@ like $* since no splitting will be performed. */ STATIC void @@ -186,6 +186,11 @@ argstr(char *p, int flag) char c; int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */ int firsteq = 1; + const char *ifs; + int ifs_split = EXP_IFS_SPLIT; + + if (flag & EXP_IFS_SPLIT) + ifs = ifsset() ? ifsval() : " \t\n"; if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) p = exptilde(p, flag); @@ -200,6 +205,10 @@ argstr(char *p, int flag) break; if ((flag & EXP_FULL) != 0) STPUTC(c, expdest); + ifs_split = 0; + break; + case CTLQUOTEEND: + ifs_split = EXP_IFS_SPLIT; break; case CTLESC: if (quotes) @@ -208,7 +217,7 @@ argstr(char *p, int flag) STPUTC(c, expdest); break; case CTLVAR: - p = evalvar(p, flag); + p = evalvar(p, (flag & ~EXP_IFS_SPLIT) | (flag & ifs_split)); break; case CTLBACKQ: case CTLBACKQ|CTLQUOTE: @@ -237,6 +246,11 @@ argstr(char *p, int flag) break; default: STPUTC(c, expdest); + if (flag & EXP_IFS_SPLIT & ifs_split && strchr(ifs, c) != NULL) { + /* We need to get the output split here... */ + recordregion(expdest - stackblock() - 1, + expdest - stackblock(), 0); + } break; } } @@ -685,7 +699,7 @@ again: /* jump here after setting a variable with ${var=text} */ /* FALLTHROUGH */ case VSMINUS: if (!set) { - argstr(p, flag); + argstr(p, flag | (apply_ifs ? EXP_IFS_SPLIT : 0)); /* * ${x-a b c} doesn't get split, but removing the * 'apply_ifs = 0' apparantly breaks ${1+"$@"}.. @@ -907,6 +921,11 @@ recordregion(int start, int end, int inquotes) if (ifslastp == NULL) { ifsp = &ifsfirst; } else { + if (ifslastp->endoff == start) { + /* extend previous area */ + ifslastp->endoff = end; + return; + } ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion)); ifslastp->next = ifsp; } diff --git a/bin/sh/parser.c b/bin/sh/parser.c index 83c125602e69..e768becbbe0d 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -1,4 +1,4 @@ -/* $NetBSD: parser.c,v 1.55 2003/08/07 09:05:37 agc Exp $ */ +/* $NetBSD: parser.c,v 1.56 2004/06/26 22:09:49 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; #else -__RCSID("$NetBSD: parser.c,v 1.55 2003/08/07 09:05:37 agc Exp $"); +__RCSID("$NetBSD: parser.c,v 1.56 2004/06/26 22:09:49 dsl Exp $"); #endif #endif /* not lint */ @@ -961,7 +961,7 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs) #endif CHECKEND(); /* set c to PEOF if at end of here document */ for (;;) { /* until end of line or end of word */ - CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */ + CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */ switch(syntax[c]) { case CNL: /* '\n' */ if (syntax == BASESYNTAX) @@ -987,57 +987,77 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs) if (c == PEOF) { USTPUTC('\\', out); pungetc(); - } else if (c == '\n') { + break; + } + if (c == '\n') { if (doprompt) setprompt(2); else setprompt(0); - } else { - if (ISDBLQUOTE() && c != '\\' && - c != '`' && c != '$' && - (c != '"' || eofmark != NULL)) - USTPUTC('\\', out); - if (SQSYNTAX[c] == CCTL) - USTPUTC(CTLESC, out); - else if (eofmark == NULL) - USTPUTC(CTLQUOTEMARK, out); - USTPUTC(c, out); - quotef++; + break; } + quotef = 1; + if (ISDBLQUOTE() && c != '\\' && + c != '`' && c != '$' && + (c != '"' || eofmark != NULL)) + USTPUTC('\\', out); + if (SQSYNTAX[c] == CCTL) + USTPUTC(CTLESC, out); + else if (eofmark == NULL) { + USTPUTC(CTLQUOTEMARK, out); + USTPUTC(c, out); + if (varnest != 0) + USTPUTC(CTLQUOTEEND, out); + break; + } + USTPUTC(c, out); break; case CSQUOTE: if (syntax != SQSYNTAX) { - if (eofmark == NULL) - USTPUTC(CTLQUOTEMARK, out); - syntax = SQSYNTAX; - break; + if (eofmark == NULL) + USTPUTC(CTLQUOTEMARK, out); + quotef = 1; + syntax = SQSYNTAX; + break; } - /* FALLTHROUGH */ + /* End of single quotes... */ + if (arinest) + syntax = ARISYNTAX; + else { + syntax = BASESYNTAX; + if (varnest != 0) + USTPUTC(CTLQUOTEEND, out); + } + break; case CDQUOTE: if (eofmark != NULL && arinest == 0 && varnest == 0) { USTPUTC(c, out); - } else { - if (arinest) { - if (c != '"' || ISDBLQUOTE()) { - syntax = ARISYNTAX; - CLRDBLQUOTE(); - } else { - syntax = DQSYNTAX; - SETDBLQUOTE(); - USTPUTC(CTLQUOTEMARK, out); - } - } else if (eofmark == NULL) { - if (c != '"' || ISDBLQUOTE()) { - syntax = BASESYNTAX; - CLRDBLQUOTE(); - } else { - syntax = DQSYNTAX; - SETDBLQUOTE(); - USTPUTC(CTLQUOTEMARK, out); - } + break; + } + quotef = 1; + if (arinest) { + if (ISDBLQUOTE()) { + syntax = ARISYNTAX; + CLRDBLQUOTE(); + } else { + syntax = DQSYNTAX; + SETDBLQUOTE(); + USTPUTC(CTLQUOTEMARK, out); } - quotef++; + break; + } + if (eofmark != NULL) + break; + if (ISDBLQUOTE()) { + if (varnest != 0) + USTPUTC(CTLQUOTEEND, out); + syntax = BASESYNTAX; + CLRDBLQUOTE(); + } else { + syntax = DQSYNTAX; + SETDBLQUOTE(); + USTPUTC(CTLQUOTEMARK, out); } break; case CVAR: /* '$' */ diff --git a/bin/sh/parser.h b/bin/sh/parser.h index 5181cece0d8d..b343c71cfff5 100644 --- a/bin/sh/parser.h +++ b/bin/sh/parser.h @@ -1,4 +1,4 @@ -/* $NetBSD: parser.h,v 1.16 2003/08/07 09:05:37 agc Exp $ */ +/* $NetBSD: parser.h,v 1.17 2004/06/26 22:09:49 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -45,7 +45,8 @@ #define CTLARI '\206' /* arithmetic expression */ #define CTLENDARI '\207' #define CTLQUOTEMARK '\210' -#define CTL_LAST '\210' /* last 'special' character */ +#define CTLQUOTEEND '\211' /* only inside ${...} */ +#define CTL_LAST '\211' /* last 'special' character */ /* variable substitution byte (follows CTLVAR) */ #define VSTYPE 0x0f /* type of variable substitution */