From af35e9a6de411e2207b63b947566e9db0d9b9d00 Mon Sep 17 00:00:00 2001 From: tg Date: Fri, 9 Oct 2015 17:48:53 +0000 Subject: [PATCH] revert most of commitid 3ec342c92b3a8874 and fixup the rest; this should bring us closer to POSIX again --- check.t | 13 ++++--------- eval.c | 24 ++++++++++++------------ exec.c | 6 ++++-- funcs.c | 15 ++++++++++++--- lex.c | 52 ++++++++++++++++++++++++++++++---------------------- main.c | 5 ++--- sh.h | 9 +++++---- syn.c | 6 +++--- 8 files changed, 72 insertions(+), 58 deletions(-) diff --git a/check.t b/check.t index 5ed38de..1642c5a 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.708 2015/10/05 17:58:57 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.709 2015/10/09 17:48:46 tg Exp $ # -*- mode: sh -*- #- # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, @@ -6505,18 +6505,13 @@ name: xxx-param-subst-qmark-1 description: Check suppresion of error message with null string. According to POSIX, it shouldn't print the error as 'word' isn't ommitted. - ksh88/93, Solaris /bin/sh and /usr/xpg4/bin/sh all print the error, - that's why the condition is reversed. + ksh88/93, Solaris /bin/sh and /usr/xpg4/bin/sh all print the error. stdin: unset foo x= echo x${foo?$x} expected-exit: 1 -# POSIX -#expected-fail: yes -#expected-stderr-pattern: !/not set/ -# common use -expected-stderr-pattern: /parameter null or not set/ +expected-stderr-pattern: !/not set/ --- name: xxx-param-_-1 # fails due to weirdness of execv stuff @@ -6532,7 +6527,7 @@ description: env-setup: !HOME=/sweet! stdin: echo ${A=a=}~ b=~ c=d~ ~ - set +o braceexpand + set -o posix unset A echo ${A=a=}~ b=~ c=d~ ~ expected-stdout: diff --git a/eval.c b/eval.c index fc0fd8f..2c2be34 100644 --- a/eval.c +++ b/eval.c @@ -3,7 +3,7 @@ /*- * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, * 2011, 2012, 2013, 2014, 2015 - * mirabilos + * mirabilos * * Provided that these terms and disclaimer and all copyright notices * are retained or reproduced in an accompanying document, permission @@ -23,7 +23,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.172 2015/09/06 19:46:59 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.173 2015/10/09 17:48:48 tg Exp $"); /* * string expansion @@ -648,6 +648,9 @@ expand( tilde_ok = 1; break; case '?': + if (*sp == CSUBST) + errorf("%s: parameter null or not set", + st->var->name); f &= ~DOBLANK; f |= DOTEMP; /* FALLTHROUGH */ @@ -743,14 +746,12 @@ expand( st = st->prev; word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS; continue; - case '?': { - char *s = Xrestpos(ds, dp, st->base); + case '?': + dp = Xrestpos(ds, dp, st->base); errorf("%s: %s", st->var->name, - dp == s ? - "parameter null or not set" : - (debunk(s, s, strlen(s) + 1), s)); - } + debunk(dp, dp, strlen(dp) + 1)); + break; case '0': case '/': case 0x100 | '#': @@ -1001,9 +1002,8 @@ expand( break; case '=': /* Note first unquoted = for ~ */ - if (!(f & DOTEMP) && !saw_eq && - (Flag(FBRACEEXPAND) || - (f & DOASNTILDE))) { + if (!(f & DOTEMP) && (!Flag(FPOSIX) || + (f & DOASNTILDE)) && !saw_eq) { saw_eq = true; tilde_ok = 1; } @@ -1287,7 +1287,7 @@ varsub(Expand *xp, const char *sp, const char *word, c = stype & 0x7F; /* test the compiler's code generator */ if (((stype < 0x100) && (ctype(c, C_SUBOP2) || c == '/' || - (((stype&0x80) ? *xp->str=='\0' : xp->str==null) ? /* undef? */ + (((stype & 0x80) ? *xp->str == '\0' : xp->str == null) ? c == '=' || c == '-' || c == '?' : c == '+'))) || stype == (0x80 | '0') || stype == (0x100 | '#') || stype == (0x100 | 'Q')) diff --git a/exec.c b/exec.c index 3e601df..3580677 100644 --- a/exec.c +++ b/exec.c @@ -23,7 +23,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.165 2015/10/09 16:11:14 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.166 2015/10/09 17:48:49 tg Exp $"); #ifndef MKSH_DEFAULT_EXECSHELL #define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh" @@ -1348,7 +1348,9 @@ call_builtin(struct tbl *tp, const char **wp, const char *where, bool resetspec) if (!tp) internal_errorf("%s: %s", where, wp[0]); builtin_argv0 = wp[0]; - builtin_spec = tobool(!resetspec && (tp->flag & SPEC_BI)); + builtin_spec = tobool(!resetspec && + /*XXX odd use of KEEPASN */ + ((tp->flag & SPEC_BI) || (Flag(FPOSIX) && (tp->flag & KEEPASN)))); shf_reopen(1, SHF_WR, shl_stdout); shl_stdout_ok = true; ksh_getopt_reset(&builtin_opt, GF_ERROR); diff --git a/funcs.c b/funcs.c index 9f097f5..af97afe 100644 --- a/funcs.c +++ b/funcs.c @@ -38,7 +38,7 @@ #endif #endif -__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.284 2015/10/09 16:11:14 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.285 2015/10/09 17:48:50 tg Exp $"); #if HAVE_KILLPG /* @@ -1305,7 +1305,8 @@ c_fgbg(const char **wp) rv = j_resume(*wp, bg); else rv = j_resume("%%", bg); - return (bg ? 0 : rv); + /* fg returns $? of the job unless POSIX */ + return ((bg | Flag(FPOSIX)) ? 0 : rv); } #endif @@ -1383,6 +1384,13 @@ c_kill(const char **wp) else shprintf("%d\n", n); } + } else if (Flag(FPOSIX)) { + n = 1; + while (n < ksh_NSIG) { + shf_puts(sigtraps[n].name, shl_stdout); + shf_putc(++n == ksh_NSIG ? '\n' : ' ', + shl_stdout); + } } else { ssize_t w, mess_cols = 0, mess_octs = 0; int j = ksh_NSIG - 1; @@ -1436,7 +1444,8 @@ void getopts_reset(int val) { if (val >= 1) { - ksh_getopt_reset(&user_opt, GF_NONAME | GF_PLUSOPT); + ksh_getopt_reset(&user_opt, GF_NONAME | + (Flag(FPOSIX) ? 0 : GF_PLUSOPT)); user_opt.optind = user_opt.uoptind = val; } } diff --git a/lex.c b/lex.c index c0388f2..df37c9b 100644 --- a/lex.c +++ b/lex.c @@ -23,7 +23,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.210 2015/10/09 16:11:16 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.211 2015/10/09 17:48:51 tg Exp $"); /* * states while lexing word @@ -234,7 +234,9 @@ yylex(int cf) if (source->flags & SF_ALIAS) { /* trailing ' ' in alias definition */ source->flags &= ~SF_ALIAS; - cf |= ALIAS; + /* POSIX: trailing space only counts if parsing simple cmd */ + if (!Flag(FPOSIX) || (cf & CMDWORD)) + cf |= ALIAS; } /* Initial state: one of SWORD SLETPAREN SHEREDELIM SBASE */ @@ -524,27 +526,32 @@ yylex(int cf) PUSH_STATE(SBQUOTE); *wp++ = COMSUB; /* - * Need to know if we are inside double quotes - * since sh/AT&T-ksh translate the \" to " in - * "`...\"...`". - * This is not done in POSIX mode (section - * 3.2.3, Double Quotes: "The backquote shall - * retain its special meaning introducing the - * other form of command substitution (see - * 3.6.3). The portion of the quoted string - * from the initial backquote and the - * characters up to the next backquote that - * is not preceded by a backslash (having - * escape characters removed) defines that - * command whose output replaces `...` when - * the word is expanded." - * Section 3.6.3, Command Substitution: - * "Within the backquoted style of command - * substitution, backslash shall retain its - * literal meaning, except when followed by - * $ ` \."). + * We need to know whether we are within double + * quotes, since most shells translate \" to " + * within "…`…\"…`…". This is not done in POSIX + * mode (§2.2.3 Double-Quotes: “The backquote + * shall retain its special meaning introducing + * the other form of command substitution (see + * Command Substitution). The portion of the + * quoted string from the initial backquote and + * the characters up to the next backquote that + * is not preceded by a , having + * escape characters removed, defines that + * command whose output replaces "`...`" when + * the word is expanded.”; §2.6.3 Command + * Substitution: “Within the backquoted style + * of command substitution, shall + * retain its literal meaning, except when + * followed by: '$', '`', or . The + * search for the matching backquote shall be + * satisfied by the first unquoted non-escaped + * backquote; during this search, if a + * non-escaped backquote is encountered[…], + * undefined results occur.”). */ statep->ls_bool = false; + if (Flag(FPOSIX)) + break; s2 = statep; base = state_info.base; while (/* CONSTCOND */ 1) { @@ -732,8 +739,9 @@ yylex(int cf) case 0: /* trailing \ is lost */ break; + case '$': + case '`': case '\\': - case '$': case '`': *wp++ = c; break; case '"': diff --git a/main.c b/main.c index 770439f..208a9da 100644 --- a/main.c +++ b/main.c @@ -34,7 +34,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/main.c,v 1.304 2015/10/09 16:11:16 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/main.c,v 1.305 2015/10/09 17:48:51 tg Exp $"); extern char **environ; @@ -1265,8 +1265,7 @@ bi_errorf(const char *fmt, ...) /* * POSIX special builtins and ksh special builtins cause - * non-interactive shells to exit. - * XXX odd use of KEEPASN; also may not want LERROR here + * non-interactive shells to exit. XXX may not want LERROR here */ if (builtin_spec) { builtin_argv0 = NULL; diff --git a/sh.h b/sh.h index f0ee8ff..96c343d 100644 --- a/sh.h +++ b/sh.h @@ -172,7 +172,7 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.746 2015/10/09 16:11:18 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.747 2015/10/09 17:48:52 tg Exp $"); #endif #define MKSH_VERSION "R51 2015/10/05" @@ -1634,9 +1634,10 @@ typedef union { #define VARASN BIT(5) /* check for var=word */ #define ARRAYVAR BIT(6) /* parse x[1 & 2] as one word */ #define ESACONLY BIT(7) /* only accept esac keyword */ -#define HEREDELIM BIT(8) /* parsing <<,<<- delimiter */ -#define LQCHAR BIT(9) /* source string contains QCHAR */ -#define HEREDOC BIT(10) /* parsing a here document body */ +#define CMDWORD BIT(8) /* parsing simple command (alias related) */ +#define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */ +#define LQCHAR BIT(10) /* source string contains QCHAR */ +#define HEREDOC BIT(11) /* parsing a here document body */ #define HERES 10 /* max number of << in line */ diff --git a/syn.c b/syn.c index bb7c07f..a5be9eb 100644 --- a/syn.c +++ b/syn.c @@ -3,7 +3,7 @@ /*- * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, * 2011, 2012, 2013, 2014, 2015 - * mirabilos + * mirabilos * * Provided that these terms and disclaimer and all copyright notices * are retained or reproduced in an accompanying document, permission @@ -23,7 +23,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.104 2015/09/06 19:47:01 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.105 2015/10/09 17:48:53 tg Exp $"); struct nesting_state { int start_token; /* token than began nesting (eg, FOR) */ @@ -294,7 +294,7 @@ get_command(int cf) t->lineno = source->line; while (/* CONSTCOND */ 1) { cf = (t->u.evalflags ? ARRAYVAR : 0) | - (XPsize(args) == 0 ? sALIAS|VARASN : 0); + (XPsize(args) == 0 ? sALIAS|VARASN : CMDWORD); switch (tpeek(cf)) { case REDIR: while ((iop = synio(cf)) != NULL) {