New functionality: assign here document to string variable directly,
without cat and temp files. Hacked in Lëtzebuerg ☺ This was the third try. Where to put this was not palpable… same for =(…)
This commit is contained in:
parent
b4948e430f
commit
230f59d064
45
check.t
45
check.t
@ -1,9 +1,9 @@
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.397 2010/12/19 20:00:53 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.398 2011/01/09 21:57:22 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 $
|
||||
#-
|
||||
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
# Thorsten Glaser <tg@mirbsd.org>
|
||||
#
|
||||
# Provided that these terms and disclaimer and all copyright notices
|
||||
@ -25,7 +25,7 @@
|
||||
# http://www.research.att.com/~gsf/public/ifs.sh
|
||||
|
||||
expected-stdout:
|
||||
@(#)MIRBSD KSH R39 2010/12/19
|
||||
@(#)MIRBSD KSH R39 2011/01/08
|
||||
description:
|
||||
Check version of shell.
|
||||
stdin:
|
||||
@ -2007,6 +2007,45 @@ stdin:
|
||||
expected-stdout:
|
||||
one
|
||||
---
|
||||
name: heredoc-10
|
||||
description:
|
||||
Check direct here document assignment
|
||||
stdin:
|
||||
x=u
|
||||
va=<<EOF
|
||||
=a $x \x40=
|
||||
EOF
|
||||
vb=<<'EOF'
|
||||
=b $x \x40=
|
||||
EOF
|
||||
function foo {
|
||||
vc=<<-EOF
|
||||
=c $x \x40=
|
||||
EOF
|
||||
}
|
||||
typeset -f foo
|
||||
foo
|
||||
# rather nonsensical, but…
|
||||
vd=<<<"=d $x \x40="
|
||||
ve=<<<'=e $x \x40='
|
||||
vf=<<<$'=f $x \x40='
|
||||
# now check
|
||||
print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} ve={$ve} vf={$vf} |"
|
||||
expected-stdout:
|
||||
function foo {
|
||||
vc= <<- EOF
|
||||
=c $x \x40=
|
||||
EOF
|
||||
|
||||
}
|
||||
| va={=a u \x40=
|
||||
} vb={=b $x \x40=
|
||||
} vc={=c u \x40=
|
||||
} vd={=d u \x40=
|
||||
} ve={=e $x \x40=
|
||||
} vf={=f $x @=
|
||||
} |
|
||||
---
|
||||
name: heredoc-quoting-unsubst
|
||||
description:
|
||||
Check for correct handling of quoted characters in
|
||||
|
167
exec.c
167
exec.c
@ -1,7 +1,7 @@
|
||||
/* $OpenBSD: exec.c,v 1.49 2009/01/29 23:27:26 jaredy Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
* Thorsten Glaser <tg@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
@ -22,18 +22,18 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.83 2010/09/15 21:08:17 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.84 2011/01/09 21:57:25 tg Exp $");
|
||||
|
||||
#ifndef MKSH_DEFAULT_EXECSHELL
|
||||
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
|
||||
#endif
|
||||
|
||||
static int comexec(struct op *, struct tbl *volatile, const char **,
|
||||
static int comexec(struct op *, struct tbl * volatile, const char **,
|
||||
int volatile, volatile int *);
|
||||
static void scriptexec(struct op *, const char **) MKSH_A_NORETURN;
|
||||
static int call_builtin(struct tbl *, const char **);
|
||||
static int iosetup(struct ioword *, struct tbl *);
|
||||
static int herein(const char *, int);
|
||||
static int herein(const char *, int, char **);
|
||||
static const char *do_selectargs(const char **, bool);
|
||||
static Test_op dbteste_isa(Test_env *, Test_meta);
|
||||
static const char *dbteste_getopnd(Test_env *, Test_op, bool);
|
||||
@ -43,7 +43,7 @@ static void dbteste_error(Test_env *, int, const char *);
|
||||
* execute command tree
|
||||
*/
|
||||
int
|
||||
execute(struct op *volatile t,
|
||||
execute(struct op * volatile t,
|
||||
volatile int flags, /* if XEXEC don't fork */
|
||||
volatile int * volatile xerrok)
|
||||
{
|
||||
@ -52,9 +52,10 @@ execute(struct op *volatile t,
|
||||
int pv[2];
|
||||
const char ** volatile ap;
|
||||
char ** volatile up;
|
||||
const char *s, *cp;
|
||||
const char *s, *ccp;
|
||||
struct ioword **iowp;
|
||||
struct tbl *tp = NULL;
|
||||
char *cp;
|
||||
|
||||
if (t == NULL)
|
||||
return (0);
|
||||
@ -71,7 +72,48 @@ execute(struct op *volatile t,
|
||||
if (trap)
|
||||
runtraps(0);
|
||||
|
||||
if (t->type == TCOM) {
|
||||
if (t->type == TCOM /* we want to run an executable... */) {
|
||||
/* check if this is 'var=<<EOF' */
|
||||
if (
|
||||
/* we have zero arguments, i.e. no programme to run */
|
||||
t->args[0] == NULL &&
|
||||
/* we have exactly one variable assignment */
|
||||
t->vars[0] != NULL && t->vars[1] == NULL &&
|
||||
/* we have exactly one I/O redirection */
|
||||
t->ioact != NULL && t->ioact[0] != NULL &&
|
||||
t->ioact[1] == NULL &&
|
||||
/* of type "here document" (or "here string") */
|
||||
(t->ioact[0]->flag & IOTYPE) == IOHERE &&
|
||||
/* the variable assignment begins with a valid varname */
|
||||
(ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] &&
|
||||
/* and has no right-hand side (i.e. "varname=") */
|
||||
ccp[0] == CHAR && ccp[1] == '=' && ccp[2] == EOS &&
|
||||
/* plus we can have a here document content */
|
||||
herein(t->ioact[0]->heredoc, t->ioact[0]->flag & IOEVAL,
|
||||
&cp) == 0 && cp && *cp) {
|
||||
char *sp = cp, *dp;
|
||||
size_t n = ccp - t->vars[0] + 2, z;
|
||||
|
||||
/* drop redirection (will be garbage collected) */
|
||||
t->ioact = NULL;
|
||||
|
||||
/* set variable to its expanded value */
|
||||
z = strlen(cp) + 1;
|
||||
if (notoktomul(z, 2) || notoktoadd(z * 2, n))
|
||||
internal_errorf(T_oomem, (unsigned long)-1);
|
||||
dp = alloc(z * 2 + n, ATEMP);
|
||||
memcpy(dp, t->vars[0], n);
|
||||
t->vars[0] = dp;
|
||||
dp += n;
|
||||
while (*sp) {
|
||||
*dp++ = QCHAR;
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
*dp = EOS;
|
||||
/* free the expanded value */
|
||||
afree(cp, APERM);
|
||||
}
|
||||
|
||||
/* Clear subst_exstat before argument expansion. Used by
|
||||
* null commands (see comexec() and c_eval()) and by c_set().
|
||||
*/
|
||||
@ -293,12 +335,12 @@ execute(struct op *volatile t,
|
||||
}
|
||||
} else { /* TSELECT */
|
||||
for (;;) {
|
||||
if (!(cp = do_selectargs(ap, is_first))) {
|
||||
if (!(ccp = do_selectargs(ap, is_first))) {
|
||||
rv = 1;
|
||||
break;
|
||||
}
|
||||
is_first = false;
|
||||
setstr(global(t->str), cp, KSH_UNWIND_ERROR);
|
||||
setstr(global(t->str), ccp, KSH_UNWIND_ERROR);
|
||||
execute(t->left, flags & XERROK, xerrok);
|
||||
}
|
||||
}
|
||||
@ -337,11 +379,11 @@ execute(struct op *volatile t,
|
||||
break;
|
||||
|
||||
case TCASE:
|
||||
cp = evalstr(t->str, DOTILDE);
|
||||
ccp = evalstr(t->str, DOTILDE);
|
||||
for (t = t->left; t != NULL && t->type == TPAT; t = t->right)
|
||||
for (ap = (const char **)t->vars; *ap; ap++)
|
||||
if ((s = evalstr(*ap, DOTILDE|DOPAT)) &&
|
||||
gmatchx(cp, s, false))
|
||||
gmatchx(ccp, s, false))
|
||||
goto Found;
|
||||
break;
|
||||
Found:
|
||||
@ -400,7 +442,7 @@ execute(struct op *volatile t,
|
||||
*/
|
||||
|
||||
static int
|
||||
comexec(struct op *t, struct tbl *volatile tp, const char **ap,
|
||||
comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
volatile int flags, volatile int *xerrok)
|
||||
{
|
||||
int i;
|
||||
@ -566,7 +608,7 @@ comexec(struct op *t, struct tbl *volatile tp, const char **ap,
|
||||
case CFUNC: { /* function call */
|
||||
volatile unsigned char old_xflag;
|
||||
volatile Tflag old_inuse;
|
||||
const char *volatile old_kshname;
|
||||
const char * volatile old_kshname;
|
||||
|
||||
if (!(tp->flag & ISSET)) {
|
||||
struct tbl *ftp;
|
||||
@ -1171,7 +1213,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
||||
case IOHERE:
|
||||
do_open = 0;
|
||||
/* herein() returns -2 if error has been printed */
|
||||
u = herein(iop->heredoc, iop->flag & IOEVAL);
|
||||
u = herein(iop->heredoc, iop->flag & IOEVAL, NULL);
|
||||
/* cp may have wrong name */
|
||||
break;
|
||||
|
||||
@ -1261,66 +1303,91 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
||||
}
|
||||
|
||||
/*
|
||||
* open here document temp file.
|
||||
* if unquoted here, expand here temp file into second temp file.
|
||||
* Process here documents by providing the content, either as
|
||||
* result (globally allocated) string or in a temp file; if
|
||||
* unquoted, the string is expanded first.
|
||||
*/
|
||||
static int
|
||||
herein(const char *content, int sub)
|
||||
hereinval(const char *content, int sub, char **resbuf, struct shf *shf)
|
||||
{
|
||||
volatile int fd = -1;
|
||||
struct source *s, *volatile osource;
|
||||
struct shf *volatile shf;
|
||||
struct temp *h;
|
||||
int i;
|
||||
|
||||
/* ksh -c 'cat << EOF' can cause this... */
|
||||
if (content == NULL) {
|
||||
warningf(true, "%s missing", "here document");
|
||||
return (-2); /* special to iosetup(): don't print error */
|
||||
}
|
||||
|
||||
/* Create temp file to hold content (done before newenv so temp
|
||||
* doesn't get removed too soon).
|
||||
*/
|
||||
h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
|
||||
if (!(shf = h->shf) || (fd = open(h->name, O_RDONLY, 0)) < 0) {
|
||||
fd = errno;
|
||||
warningf(true, "can't %s temporary file %s: %s",
|
||||
!shf ? "create" : "open",
|
||||
h->name, strerror(fd));
|
||||
if (shf)
|
||||
shf_close(shf);
|
||||
return (-2 /* special to iosetup(): don't print error */);
|
||||
}
|
||||
const char *ccp;
|
||||
struct source *s, *osource;
|
||||
|
||||
osource = source;
|
||||
newenv(E_ERRH);
|
||||
i = sigsetjmp(e->jbuf, 0);
|
||||
if (i) {
|
||||
if (sigsetjmp(e->jbuf, 0)) {
|
||||
source = osource;
|
||||
quitenv(shf);
|
||||
close(fd);
|
||||
return (-2); /* special to iosetup(): don't print error */
|
||||
/* special to iosetup(): don't print error */
|
||||
return (-2);
|
||||
}
|
||||
if (sub) {
|
||||
/* Do substitutions on the content of heredoc */
|
||||
/* do substitutions on the content of heredoc */
|
||||
s = pushs(SSTRING, ATEMP);
|
||||
s->start = s->str = content;
|
||||
source = s;
|
||||
if (yylex(ONEWORD|HEREDOC) != LWORD)
|
||||
internal_errorf("%s: %s", "herein", "yylex");
|
||||
source = osource;
|
||||
shf_puts(evalstr(yylval.cp, 0), shf);
|
||||
ccp = evalstr(yylval.cp, 0);
|
||||
} else
|
||||
shf_puts(content, shf);
|
||||
ccp = content;
|
||||
|
||||
if (resbuf == NULL)
|
||||
shf_puts(ccp, shf);
|
||||
else
|
||||
strdupx(*resbuf, ccp, APERM);
|
||||
|
||||
quitenv(NULL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
herein(const char *content, int sub, char **resbuf)
|
||||
{
|
||||
int fd = -1;
|
||||
struct shf *shf;
|
||||
struct temp *h;
|
||||
int i;
|
||||
|
||||
/* ksh -c 'cat << EOF' can cause this... */
|
||||
if (content == NULL) {
|
||||
warningf(true, "%s missing", "here document");
|
||||
/* special to iosetup(): don't print error */
|
||||
return (-2);
|
||||
}
|
||||
|
||||
/* skip all the fd setup if we just want the value */
|
||||
if (resbuf != NULL)
|
||||
return (hereinval(content, sub, resbuf, NULL));
|
||||
|
||||
/*
|
||||
* Create temp file to hold content (done before newenv
|
||||
* so temp doesn't get removed too soon).
|
||||
*/
|
||||
h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
|
||||
if (!(shf = h->shf) || (fd = open(h->name, O_RDONLY, 0)) < 0) {
|
||||
i = errno;
|
||||
warningf(true, "can't %s temporary file %s: %s",
|
||||
!shf ? "create" : "open", h->name, strerror(i));
|
||||
if (shf)
|
||||
shf_close(shf);
|
||||
/* special to iosetup(): don't print error */
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if (hereinval(content, sub, NULL, shf) == -2) {
|
||||
close(fd);
|
||||
/* special to iosetup(): don't print error */
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if (shf_close(shf) == EOF) {
|
||||
i = errno;
|
||||
close(fd);
|
||||
warningf(true, "%s: %s: %s", "write", h->name, strerror(i));
|
||||
return (-2); /* special to iosetup(): don't print error */
|
||||
/* special to iosetup(): don't print error */
|
||||
return (-2);
|
||||
}
|
||||
|
||||
return (fd);
|
||||
|
14
funcs.c
14
funcs.c
@ -4,7 +4,8 @@
|
||||
/* $OpenBSD: c_ulimit.c,v 1.17 2008/03/21 12:51:19 millert Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||
* 2010, 2011
|
||||
* Thorsten Glaser <tg@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
@ -25,7 +26,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.164 2010/11/01 17:29:02 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.165 2011/01/09 21:57:26 tg Exp $");
|
||||
|
||||
#if HAVE_KILLPG
|
||||
/*
|
||||
@ -1174,8 +1175,10 @@ c_typeset(const char **wp)
|
||||
char *s = str_val(vp);
|
||||
|
||||
shf_putc('=', shl_stdout);
|
||||
/* AT&T ksh can't have
|
||||
* justified integers.. */
|
||||
/*
|
||||
* AT&T ksh can't have
|
||||
* justified integers...
|
||||
*/
|
||||
if ((vp->flag &
|
||||
(INTEGER|LJUST|RJUST)) ==
|
||||
INTEGER)
|
||||
@ -3464,8 +3467,7 @@ c_cat(const char **wp)
|
||||
|
||||
/* XXX uses malloc instead of lalloc (for alignment/speed) */
|
||||
if ((buf = malloc(MKSH_CAT_BUFSIZ)) == NULL) {
|
||||
bi_errorf("can't allocate %lu data bytes",
|
||||
(unsigned long)MKSH_CAT_BUFSIZ);
|
||||
bi_errorf(T_oomem, (unsigned long)MKSH_CAT_BUFSIZ);
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
9
lalloc.c
9
lalloc.c
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2009, 2010
|
||||
* Copyright (c) 2009, 2010, 2011
|
||||
* Thorsten Glaser <tg@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.13 2010/09/14 21:26:14 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.14 2011/01/09 21:57:27 tg Exp $");
|
||||
|
||||
/* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */
|
||||
#if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0)
|
||||
@ -70,7 +70,7 @@ findptr(ALLOC_ITEM **lpp, char *ptr, Area *ap)
|
||||
void *
|
||||
aresize2(void *ptr, size_t fac1, size_t fac2, Area *ap)
|
||||
{
|
||||
if (fac1 && fac2 && (SIZE_MAX / fac1 < fac2))
|
||||
if (notoktomul(fac1, fac2))
|
||||
internal_errorf(T_intovfl, (unsigned long)fac1, '*',
|
||||
(unsigned long)fac2);
|
||||
return (aresize(ptr, fac1 * fac2, ap));
|
||||
@ -95,8 +95,7 @@ aresize(void *ptr, size_t numb, Area *ap)
|
||||
|| ALLOC_ISUNALIGNED(lp)
|
||||
#endif
|
||||
)
|
||||
internal_errorf("can't allocate %lu data bytes",
|
||||
(unsigned long)numb);
|
||||
internal_errorf(T_oomem, (unsigned long)numb);
|
||||
/* this only works because Area is an ALLOC_ITEM */
|
||||
lp->next = ap->next;
|
||||
ap->next = lp;
|
||||
|
22
misc.c
22
misc.c
@ -2,7 +2,7 @@
|
||||
/* $OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
* Thorsten Glaser <tg@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
@ -29,7 +29,7 @@
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.148 2010/09/19 19:28:22 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.149 2011/01/09 21:57:27 tg Exp $");
|
||||
|
||||
unsigned char chtypes[UCHAR_MAX + 1]; /* type bits for unsigned char */
|
||||
|
||||
@ -921,25 +921,33 @@ void
|
||||
print_value_quoted(const char *s)
|
||||
{
|
||||
const char *p;
|
||||
int inquote = 0;
|
||||
bool inquote = false;
|
||||
|
||||
/* Test if any quotes are needed */
|
||||
/* first, check whether any quotes are needed */
|
||||
for (p = s; *p; p++)
|
||||
if (ctype(*p, C_QUOTE))
|
||||
break;
|
||||
if (!*p) {
|
||||
/* nope, use the shortcut */
|
||||
shf_puts(s, shl_stdout);
|
||||
return;
|
||||
}
|
||||
|
||||
/* quote via state machine */
|
||||
for (p = s; *p; p++) {
|
||||
if (*p == '\'') {
|
||||
if (inquote)
|
||||
/*
|
||||
* multiple '''s or any ' at beginning of string
|
||||
* look nicer this way than when simply substituting
|
||||
*/
|
||||
if (inquote) {
|
||||
shf_putc('\'', shl_stdout);
|
||||
inquote = false;
|
||||
}
|
||||
shf_putc('\\', shl_stdout);
|
||||
inquote = 0;
|
||||
} else if (!inquote) {
|
||||
shf_putc('\'', shl_stdout);
|
||||
inquote = 1;
|
||||
inquote = true;
|
||||
}
|
||||
shf_putc(*p, shl_stdout);
|
||||
}
|
||||
|
14
mksh.1
14
mksh.1
@ -1,7 +1,8 @@
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.243 2010/12/19 20:00:55 tg Exp $
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.244 2011/01/09 21:57:27 tg Exp $
|
||||
.\" $OpenBSD: ksh.1,v 1.138 2010/09/20 07:41:17 jmc Exp $
|
||||
.\"-
|
||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||
.\" 2010, 2011
|
||||
.\" Thorsten Glaser <tg@mirbsd.org>
|
||||
.\"
|
||||
.\" Provided that these terms and disclaimer and all copyright notices
|
||||
@ -71,7 +72,7 @@
|
||||
.\" with -mandoc, it might implement .Mx itself, but we want to
|
||||
.\" use our own definition. And .Dd must come *first*, always.
|
||||
.\"
|
||||
.Dd $Mdocdate: December 19 2010 $
|
||||
.Dd $Mdocdate: January 9 2011 $
|
||||
.\"
|
||||
.\" Check which macro package we use
|
||||
.\"
|
||||
@ -6073,7 +6074,14 @@ code fails because of the parenthesis asymmetry
|
||||
.Pq RedHat BZ#496791 .
|
||||
A workaround exists; use
|
||||
.Ql x=$(cat) \*(Lt\*(Lt"EOF"
|
||||
or the newline-keeping
|
||||
.Ql x=\*(Lt\*(Lt"EOF"
|
||||
instead to merely slurp the string.
|
||||
Of course, in this case, the form
|
||||
.Ql x=$(case $foo in (bar) ...
|
||||
actually recommended by
|
||||
.St -p1003.1
|
||||
would work as well, but we use it as an example of this parser bug.
|
||||
.Bd -literal -offset indent
|
||||
x=$(case $foo in bar) echo $bar ;; *) echo $baz ;; esac)
|
||||
# above fails to parse; below is the workaround
|
||||
|
12
sh.h
12
sh.h
@ -9,7 +9,7 @@
|
||||
/* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
* Thorsten Glaser <tg@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
@ -154,9 +154,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef EXTERN
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.420 2010/12/19 20:00:56 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.421 2011/01/09 21:57:29 tg Exp $");
|
||||
#endif
|
||||
#define MKSH_VERSION "R39 2010/12/19"
|
||||
#define MKSH_VERSION "R39 2011/01/08"
|
||||
|
||||
#ifndef MKSH_INCLUDES_ONLY
|
||||
|
||||
@ -630,6 +630,7 @@ extern const struct shoption options[];
|
||||
EXTERN char null[] I__("");
|
||||
/* helpers for string pooling */
|
||||
EXTERN const char T_intovfl[] I__("integer overflow %lu %c %lu prevented");
|
||||
EXTERN const char T_oomem[] I__("can't allocate %lu data bytes");
|
||||
#if defined(__GNUC__)
|
||||
/* trust this to have string pooling; -Wformat bitches otherwise */
|
||||
#define T_synerr "syntax error"
|
||||
@ -1199,7 +1200,7 @@ struct ioword {
|
||||
#define DB_BE 4 /* an inserted -BE */
|
||||
#define DB_PAT 5 /* a pattern argument */
|
||||
|
||||
#define X_EXTRA 8 /* this many extra bytes in X string */
|
||||
#define X_EXTRA 20 /* this many extra bytes in X string */
|
||||
|
||||
typedef struct XString {
|
||||
char *end, *beg; /* end, begin of string */
|
||||
@ -1397,6 +1398,8 @@ EXTERN int histsize; /* history size */
|
||||
/* user and system time of last j_waitjed job */
|
||||
EXTERN struct timeval j_usrtime, j_systime;
|
||||
|
||||
#define notoktomul(fac1, fac2) ((fac1) && (fac2) && \
|
||||
(SIZE_MAX / (fac1) < (fac2)))
|
||||
#define notoktoadd(val, cnst) ((val) > (SIZE_MAX - (cnst)))
|
||||
#define checkoktoadd(val, cnst) do { \
|
||||
if (notoktoadd((val), (cnst))) \
|
||||
@ -1637,6 +1640,7 @@ int xstrcmp(const void *, const void *);
|
||||
void ksh_getopt_reset(Getopt *, int);
|
||||
int ksh_getopt(const char **, Getopt *, const char *);
|
||||
void print_value_quoted(const char *);
|
||||
char *quote_value(const char *);
|
||||
void print_columns(struct shf *, int,
|
||||
char *(*)(char *, int, int, const void *),
|
||||
const void *, int, int, bool);
|
||||
|
Loading…
x
Reference in New Issue
Block a user