both mksh(1) and POSIX say: "$@" should always generate multiple words
issue in pdksh reported in IRC by engla, thanks!
This commit is contained in:
parent
74e2ef8b0b
commit
817aeb8fdb
6
Build.sh
6
Build.sh
@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.622 2013/02/19 18:45:15 tg Exp $'
|
||||
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.623 2013/02/23 20:03:25 tg Exp $'
|
||||
#-
|
||||
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011, 2012, 2013
|
||||
@ -1532,7 +1532,7 @@ else
|
||||
#define EXTERN
|
||||
#define MKSH_INCLUDES_ONLY
|
||||
#include "sh.h"
|
||||
__RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.622 2013/02/19 18:45:15 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.623 2013/02/23 20:03:25 tg Exp $");
|
||||
int main(void) { printf("Hello, World!\n"); return (0); }
|
||||
EOF
|
||||
case $cm in
|
||||
@ -2120,7 +2120,7 @@ addsrcs USE_PRINTF_BUILTIN printf.c
|
||||
test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
|
||||
test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
|
||||
test -n "$LDSTATIC" && add_cppflags -DMKSH_OPTSTATIC
|
||||
add_cppflags -DMKSH_BUILD_R=431
|
||||
add_cppflags -DMKSH_BUILD_R=440
|
||||
|
||||
$e $bi$me: Finished configuration testing, now producing output.$ao
|
||||
|
||||
|
4
Makefile
4
Makefile
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/Makefile,v 1.112 2013/02/18 22:55:37 tg Exp $
|
||||
# $MirOS: src/bin/mksh/Makefile,v 1.113 2013/02/23 20:03:27 tg Exp $
|
||||
#-
|
||||
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011, 2012, 2013
|
||||
@ -55,7 +55,7 @@ CPPFLAGS+= -DMKSH_ASSUME_UTF8 -DMKSH_DISABLE_DEPRECATED \
|
||||
-DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 \
|
||||
-DHAVE_SYS_ERRLIST_DECL=1 -DHAVE_SYS_SIGLIST_DECL=1 \
|
||||
-DHAVE_PERSISTENT_HISTORY=1 -DHAVE_SILENT_IDIVWRAPV=0 \
|
||||
-DMKSH_BUILD_R=431
|
||||
-DMKSH_BUILD_R=440
|
||||
CPPFLAGS+= -D${${PROG:L}_tf:C/(Mir${MAN:E}{0,1}){2}/4/:S/x/mksh_BUILD/:U}
|
||||
COPTS+= -std=c99 -Wall
|
||||
.endif
|
||||
|
12
check.t
12
check.t
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.597 2013/02/19 18:45:17 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.598 2013/02/23 20:03:27 tg Exp $
|
||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
||||
@ -29,7 +29,7 @@
|
||||
# http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD
|
||||
|
||||
expected-stdout:
|
||||
@(#)MIRBSD KSH R43 2013/02/19
|
||||
@(#)MIRBSD KSH R44 2013/02/23
|
||||
description:
|
||||
Check version of shell.
|
||||
stdin:
|
||||
@ -38,7 +38,7 @@ name: KSH_VERSION
|
||||
category: shell:legacy-no
|
||||
---
|
||||
expected-stdout:
|
||||
@(#)LEGACY KSH R43 2013/02/19
|
||||
@(#)LEGACY KSH R44 2013/02/23
|
||||
description:
|
||||
Check version of legacy shell.
|
||||
stdin:
|
||||
@ -3466,10 +3466,10 @@ stdin:
|
||||
showargs 3 $@
|
||||
showargs 4 "$@"
|
||||
expected-stdout:
|
||||
<1> <A B C>
|
||||
<1> <A> <B> <C>
|
||||
<2> <ABC>
|
||||
<3> <A B C>
|
||||
<4> <A B C>
|
||||
<3> <A> <B> <C>
|
||||
<4> <A> <B> <C>
|
||||
---
|
||||
name: IFS-space-colon-1
|
||||
description:
|
||||
|
151
eval.c
151
eval.c
@ -23,7 +23,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.136 2013/02/10 23:43:59 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.137 2013/02/23 20:03:30 tg Exp $");
|
||||
|
||||
/*
|
||||
* string expansion
|
||||
@ -33,15 +33,21 @@ __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.136 2013/02/10 23:43:59 tg Exp $");
|
||||
*/
|
||||
|
||||
/* expansion generator state */
|
||||
typedef struct Expand {
|
||||
/* int type; */ /* see expand() */
|
||||
const char *str; /* string */
|
||||
typedef struct {
|
||||
/* not including an "int type;" member, see expand() */
|
||||
/* string */
|
||||
const char *str;
|
||||
/* source */
|
||||
union {
|
||||
const char **strv; /* string[] */
|
||||
struct shf *shf; /* file */
|
||||
} u; /* source */
|
||||
struct tbl *var; /* variable in ${var..} */
|
||||
bool split; /* split "$@" / call waitlast $() */
|
||||
/* string[] */
|
||||
const char **strv;
|
||||
/* file */
|
||||
struct shf *shf;
|
||||
} u;
|
||||
/* variable in ${var...} */
|
||||
struct tbl *var;
|
||||
/* split "$@" / call waitlast in $() */
|
||||
bool split;
|
||||
} Expand;
|
||||
|
||||
#define XBASE 0 /* scanning original */
|
||||
@ -198,33 +204,46 @@ typedef struct SubType {
|
||||
} SubType;
|
||||
|
||||
void
|
||||
expand(const char *cp, /* input word */
|
||||
XPtrV *wp, /* output words */
|
||||
int f) /* DO* flags */
|
||||
expand(
|
||||
/* input word */
|
||||
const char *ccp,
|
||||
/* output words */
|
||||
XPtrV *wp,
|
||||
/* DO* flags */
|
||||
int f)
|
||||
{
|
||||
int c = 0;
|
||||
int type; /* expansion type */
|
||||
int quote = 0; /* quoted */
|
||||
XString ds; /* destination string */
|
||||
char *dp; /* destination */
|
||||
const char *sp; /* source */
|
||||
int fdo, word; /* second pass flags; have word */
|
||||
int doblank; /* field splitting of parameter/command subst */
|
||||
/* expansion type */
|
||||
int type;
|
||||
/* quoted */
|
||||
int quote = 0;
|
||||
/* destination string and live pointer */
|
||||
XString ds;
|
||||
char *dp;
|
||||
/* source */
|
||||
const char *sp;
|
||||
/* second pass flags */
|
||||
int fdo;
|
||||
/* have word */
|
||||
int word;
|
||||
/* field splitting of parameter/command substitution */
|
||||
int doblank;
|
||||
/* expansion variables */
|
||||
Expand x = {
|
||||
/* expansion variables */
|
||||
NULL, { NULL }, NULL, 0
|
||||
};
|
||||
SubType st_head, *st;
|
||||
/* For trailing newlines in COMSUB */
|
||||
/* record number of trailing newlines in COMSUB */
|
||||
int newlines = 0;
|
||||
bool saw_eq, make_magic;
|
||||
int tilde_ok;
|
||||
size_t len;
|
||||
char *cp;
|
||||
|
||||
if (cp == NULL)
|
||||
if (ccp == NULL)
|
||||
internal_errorf("expand(NULL)");
|
||||
/* for alias, readonly, set, typeset commands */
|
||||
if ((f & DOVACHECK) && is_wdvarassign(cp)) {
|
||||
if ((f & DOVACHECK) && is_wdvarassign(ccp)) {
|
||||
f &= ~(DOVACHECK|DOBLANK|DOGLOB|DOTILDE);
|
||||
f |= DOASNTILDE;
|
||||
}
|
||||
@ -238,7 +257,7 @@ expand(const char *cp, /* input word */
|
||||
/* init destination string */
|
||||
Xinit(ds, dp, 128, ATEMP);
|
||||
type = XBASE;
|
||||
sp = cp;
|
||||
sp = ccp;
|
||||
fdo = 0;
|
||||
saw_eq = false;
|
||||
/* must be 1/0 */
|
||||
@ -317,7 +336,6 @@ expand(const char *cp, /* input word */
|
||||
*dp++ = ')'; *dp++ = ')';
|
||||
} else {
|
||||
struct tbl v;
|
||||
char *p;
|
||||
|
||||
v.flag = DEFINED|ISSET|INTEGER;
|
||||
/* not default */
|
||||
@ -326,9 +344,10 @@ expand(const char *cp, /* input word */
|
||||
v_evaluate(&v, substitute(sp, 0),
|
||||
KSH_UNWIND_ERROR, true);
|
||||
sp = strnul(sp) + 1;
|
||||
for (p = str_val(&v); *p; ) {
|
||||
cp = str_val(&v);
|
||||
while (*cp) {
|
||||
Xcheck(ds, dp);
|
||||
*dp++ = *p++;
|
||||
*dp++ = *cp++;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@ -394,8 +413,7 @@ expand(const char *cp, /* input word */
|
||||
if (stype)
|
||||
sp += slen;
|
||||
switch (stype & 0x17F) {
|
||||
case 0x100 | '#':
|
||||
{
|
||||
case 0x100 | '#': {
|
||||
char *beg, *end;
|
||||
mksh_ari_t seed;
|
||||
register uint32_t h;
|
||||
@ -416,8 +434,7 @@ expand(const char *cp, /* input word */
|
||||
(unsigned int)h);
|
||||
break;
|
||||
}
|
||||
case 0x100 | 'Q':
|
||||
{
|
||||
case 0x100 | 'Q': {
|
||||
struct shf shf;
|
||||
|
||||
shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf);
|
||||
@ -839,7 +856,10 @@ expand(const char *cp, /* input word */
|
||||
if (c == 0) {
|
||||
if (quote && !x.split)
|
||||
continue;
|
||||
/* this is so we don't terminate */
|
||||
c = ' ';
|
||||
/* now force-emit a word */
|
||||
goto emit_word;
|
||||
}
|
||||
if (quote && x.split) {
|
||||
/* terminate word for "$@" */
|
||||
@ -851,13 +871,13 @@ expand(const char *cp, /* input word */
|
||||
|
||||
case XCOM:
|
||||
if (newlines) {
|
||||
/* Spit out saved NLs */
|
||||
/* spit out saved NLs */
|
||||
c = '\n';
|
||||
--newlines;
|
||||
} else {
|
||||
while ((c = shf_getc(x.u.shf)) == 0 || c == '\n')
|
||||
if (c == '\n')
|
||||
/* Save newlines */
|
||||
/* save newlines */
|
||||
newlines++;
|
||||
if (newlines && c != EOF) {
|
||||
shf_ungetc(c, x.u.shf);
|
||||
@ -895,21 +915,21 @@ expand(const char *cp, /* input word */
|
||||
*/
|
||||
if (word == IFS_WORD ||
|
||||
(!ctype(c, C_IFSWS) && c && word == IFS_NWS)) {
|
||||
char *p;
|
||||
|
||||
emit_word:
|
||||
*dp++ = '\0';
|
||||
p = Xclose(ds, dp);
|
||||
cp = Xclose(ds, dp);
|
||||
if (fdo & DOBRACE)
|
||||
/* also does globbing */
|
||||
alt_expand(wp, p, p,
|
||||
p + Xlength(ds, (dp - 1)),
|
||||
alt_expand(wp, cp, cp,
|
||||
cp + Xlength(ds, (dp - 1)),
|
||||
fdo | (f & DOMARKDIRS));
|
||||
else if (fdo & DOGLOB)
|
||||
glob(p, wp, tobool(f & DOMARKDIRS));
|
||||
glob(cp, wp, tobool(f & DOMARKDIRS));
|
||||
else if ((f & DOPAT) || !(fdo & DOMAGIC))
|
||||
XPput(*wp, p);
|
||||
XPput(*wp, cp);
|
||||
else
|
||||
XPput(*wp, debunk(p, p, strlen(p) + 1));
|
||||
XPput(*wp, debunk(cp, cp,
|
||||
strlen(cp) + 1));
|
||||
fdo = 0;
|
||||
saw_eq = false;
|
||||
tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0;
|
||||
@ -920,10 +940,8 @@ expand(const char *cp, /* input word */
|
||||
return;
|
||||
} else if (type == XSUB && ctype(c, C_IFS) &&
|
||||
!ctype(c, C_IFSWS) && Xlength(ds, dp) == 0) {
|
||||
char *p;
|
||||
|
||||
*(p = alloc(1, ATEMP)) = '\0';
|
||||
XPput(*wp, p);
|
||||
*(cp = alloc(1, ATEMP)) = '\0';
|
||||
XPput(*wp, cp);
|
||||
type = XSUBMID;
|
||||
}
|
||||
if (word != IFS_NWS)
|
||||
@ -932,10 +950,8 @@ expand(const char *cp, /* input word */
|
||||
if (type == XSUB) {
|
||||
if (word == IFS_NWS &&
|
||||
Xlength(ds, dp) == 0) {
|
||||
char *p;
|
||||
|
||||
*(p = alloc(1, ATEMP)) = '\0';
|
||||
XPput(*wp, p);
|
||||
*(cp = alloc(1, ATEMP)) = '\0';
|
||||
XPput(*wp, cp);
|
||||
}
|
||||
type = XSUBMID;
|
||||
}
|
||||
@ -1002,18 +1018,17 @@ expand(const char *cp, /* input word */
|
||||
if (type == XBASE &&
|
||||
(f & (DOTILDE|DOASNTILDE)) &&
|
||||
(tilde_ok & 2)) {
|
||||
const char *p;
|
||||
char *dp_x;
|
||||
const char *tcp;
|
||||
char *tdp = dp;
|
||||
|
||||
dp_x = dp;
|
||||
p = maybe_expand_tilde(sp,
|
||||
&ds, &dp_x,
|
||||
tcp = maybe_expand_tilde(sp,
|
||||
&ds, &tdp,
|
||||
f & DOASNTILDE);
|
||||
if (p) {
|
||||
if (dp != dp_x)
|
||||
if (tcp) {
|
||||
if (dp != tdp)
|
||||
word = IFS_WORD;
|
||||
dp = dp_x;
|
||||
sp = p;
|
||||
dp = tdp;
|
||||
sp = tcp;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -1176,8 +1191,10 @@ varsub(Expand *xp, const char *sp, const char *word,
|
||||
c = sp[0];
|
||||
if (c == '*' || c == '@') {
|
||||
switch (stype & 0x17F) {
|
||||
case '=': /* can't assign to a vector */
|
||||
case '%': /* can't trim a vector (yet) */
|
||||
/* can't assign to a vector */
|
||||
case '=':
|
||||
/* can't trim a vector (yet) */
|
||||
case '%':
|
||||
case '#':
|
||||
case '0':
|
||||
case '/':
|
||||
@ -1204,8 +1221,10 @@ varsub(Expand *xp, const char *sp, const char *word,
|
||||
XPtrV wv;
|
||||
|
||||
switch (stype & 0x17F) {
|
||||
case '=': /* can't assign to a vector */
|
||||
case '%': /* can't trim a vector (yet) */
|
||||
/* can't assign to a vector */
|
||||
case '=':
|
||||
/* can't trim a vector (yet) */
|
||||
case '%':
|
||||
case '#':
|
||||
case '?':
|
||||
case '0':
|
||||
@ -1495,11 +1514,11 @@ globit(XString *xs, /* dest string */
|
||||
*/
|
||||
if ((check & GF_EXCHECK) ||
|
||||
((check & GF_MARKDIR) && (check & GF_GLOBBED))) {
|
||||
#define stat_check() (stat_done ? stat_done : \
|
||||
(stat_done = stat(Xstring(*xs, xp), &statb) < 0 \
|
||||
? -1 : 1))
|
||||
#define stat_check() (stat_done ? stat_done : (stat_done = \
|
||||
stat(Xstring(*xs, xp), &statb) < 0 ? -1 : 1))
|
||||
struct stat lstatb, statb;
|
||||
int stat_done = 0; /* -1: failed, 1 ok */
|
||||
/* -1: failed, 1 ok, 0 not yet done */
|
||||
int stat_done = 0;
|
||||
|
||||
if (mksh_lstat(Xstring(*xs, xp), &lstatb) < 0)
|
||||
return;
|
||||
|
6
sh.h
6
sh.h
@ -164,9 +164,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef EXTERN
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.639 2013/02/19 18:45:22 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.640 2013/02/23 20:03:31 tg Exp $");
|
||||
#endif
|
||||
#define MKSH_VERSION "R43 2013/02/19"
|
||||
#define MKSH_VERSION "R44 2013/02/23"
|
||||
|
||||
/* arithmetic types: C implementation */
|
||||
#if !HAVE_CAN_INTTYPES
|
||||
@ -511,7 +511,7 @@ char *ucstrstr(char *, const char *);
|
||||
#define mkssert(e) do { } while (/* CONSTCOND */ 0)
|
||||
#endif
|
||||
|
||||
#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 431)
|
||||
#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 440)
|
||||
#error Must run Build.sh to compile this.
|
||||
int
|
||||
im_sorry_dave(void)
|
||||
|
Loading…
x
Reference in New Issue
Block a user