• fix wtf(1) by keeping the paren in ${foo#\(} properly escaped in COMSUB

• merge tputS and wdstrip_internal
⇒ net save: 604 .text 0 .data 0 .bss (MirBSD/i386)
This commit is contained in:
tg 2011-05-02 22:52:54 +00:00
parent d69ffbf9e0
commit 69f98bca9a
6 changed files with 98 additions and 137 deletions

18
check.t
View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.447 2011/04/22 21:44:33 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.448 2011/05/02 22:52:49 tg Exp $
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas 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: 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 $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
@ -25,7 +25,7 @@
# http://www.research.att.com/~gsf/public/ifs.sh # http://www.research.att.com/~gsf/public/ifs.sh
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R39 2011/04/22 @(#)MIRBSD KSH R39 2011/05/02
description: description:
Check version of shell. Check version of shell.
stdin: stdin:
@ -7392,7 +7392,7 @@ stdin:
echo "fo\ob\"a\`r\'b\$az" echo "fo\ob\"a\`r\'b\$az"
echo 'fo\ob\"a\`r'\''b\$az' echo 'fo\ob\"a\`r'\''b\$az'
#OSUBST_CSUBST_OPAT_SPAT_CPAT #OSUBST_CSUBST_OPAT_SPAT_CPAT
[[ ${foo#blub} = @(bar|baz) ]] [[ ${foo#bl\(u\)b} = @(bar|baz) ]]
#heredoc_closed #heredoc_closed
x=$(cat <<EOFN x=$(cat <<EOFN
note there must be no space between EOFN and ) note there must be no space between EOFN and )
@ -7809,22 +7809,22 @@ expected-stdout:
x=$(( echo fo\ob\"a\`r\'b\$az ; echo "fo\ob\"a\`r\'b\$az" ; echo "fo\\ob\\\"a\\\`r"\'"b\\\$az" ) | tr u x ) x=$(( echo fo\ob\"a\`r\'b\$az ; echo "fo\ob\"a\`r\'b\$az" ; echo "fo\\ob\\\"a\\\`r"\'"b\\\$az" ) | tr u x )
} }
inline_OSUBST_CSUBST_OPAT_SPAT_CPAT() { inline_OSUBST_CSUBST_OPAT_SPAT_CPAT() {
[[ ${foo#blub} = @(bar|baz) ]] [[ ${foo#bl\(u\)b} = @(bar|baz) ]]
} }
inline_OSUBST_CSUBST_OPAT_SPAT_CPAT() { inline_OSUBST_CSUBST_OPAT_SPAT_CPAT() {
[[ ${foo#blub} = @(bar|baz) ]] [[ ${foo#bl\(u\)b} = @(bar|baz) ]]
} }
function comsub_OSUBST_CSUBST_OPAT_SPAT_CPAT { x=$( function comsub_OSUBST_CSUBST_OPAT_SPAT_CPAT { x=$(
[[ ${foo#blub} = @(bar|baz) ]] [[ ${foo#bl\(u\)b} = @(bar|baz) ]]
); } ); }
function comsub_OSUBST_CSUBST_OPAT_SPAT_CPAT { function comsub_OSUBST_CSUBST_OPAT_SPAT_CPAT {
x=$([[ ${foo#blub} = @(bar|baz) ]] ) x=$([[ ${foo#bl\(u\)b} = @(bar|baz) ]] )
} }
function reread_OSUBST_CSUBST_OPAT_SPAT_CPAT { x=$(( function reread_OSUBST_CSUBST_OPAT_SPAT_CPAT { x=$((
[[ ${foo#blub} = @(bar|baz) ]] [[ ${foo#bl\(u\)b} = @(bar|baz) ]]
)|tr u x); } )|tr u x); }
function reread_OSUBST_CSUBST_OPAT_SPAT_CPAT { function reread_OSUBST_CSUBST_OPAT_SPAT_CPAT {
x=$(( [[ ${foo#blub} = @(bar|baz) ]] ) | tr u x ) x=$(( [[ ${foo#bl\(u\)b} = @(bar|baz) ]] ) | tr u x )
} }
inline_heredoc_closed() { inline_heredoc_closed() {
x=$(cat <<EOFN x=$(cat <<EOFN

11
eval.c
View File

@ -22,7 +22,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.103 2011/03/28 08:27:08 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.104 2011/05/02 22:52:51 tg Exp $");
/* /*
* string expansion * string expansion
@ -398,11 +398,11 @@ expand(const char *cp, /* input word */
end[-2] = EOS; end[-2] = EOS;
sp += end - beg - 1; sp += end - beg - 1;
} }
evaluate(substitute(stg = wdstrip(beg, false, false), 0), evaluate(substitute(stg = wdstrip(beg, 0), 0),
&from, KSH_UNWIND_ERROR, true); &from, KSH_UNWIND_ERROR, true);
afree(stg, ATEMP); afree(stg, ATEMP);
if (end) { if (end) {
evaluate(substitute(stg = wdstrip(mid, false, false), 0), evaluate(substitute(stg = wdstrip(mid, 0), 0),
&num, KSH_UNWIND_ERROR, true); &num, KSH_UNWIND_ERROR, true);
afree(stg, ATEMP); afree(stg, ATEMP);
} }
@ -441,10 +441,11 @@ expand(const char *cp, /* input word */
else else
d[-2] = EOS; d[-2] = EOS;
sp += (d ? d : p) - s - 1; sp += (d ? d : p) - s - 1;
tpat0 = wdstrip(s, true, true); tpat0 = wdstrip(s,
WDS_KEEPQ | WDS_MAGIC);
pat = substitute(tpat0, 0); pat = substitute(tpat0, 0);
if (d) { if (d) {
d = wdstrip(p, true, false); d = wdstrip(p, WDS_KEEPQ);
rrep = substitute(d, 0); rrep = substitute(d, 0);
afree(d, ATEMP); afree(d, ATEMP);
} else } else

4
lex.c
View File

@ -22,7 +22,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.146 2011/04/22 12:10:14 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.147 2011/05/02 22:52:51 tg Exp $");
/* /*
* states while lexing word * states while lexing word
@ -763,7 +763,7 @@ yylex(int cf)
*/ */
*wp = EOS; *wp = EOS;
sp = Xstring(ws, wp); sp = Xstring(ws, wp);
dp = wdstrip(sp, true, false); dp = wdstrip(sp, WDS_KEEPQ);
s = pushs(SREREAD, source->areap); s = pushs(SREREAD, source->areap);
s->start = s->str = s->u.freeme = dp; s->start = s->str = s->u.freeme = dp;
s->next = source; s->next = source;

9
sh.h
View File

@ -151,9 +151,9 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.466 2011/04/22 21:44:35 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.467 2011/05/02 22:52:52 tg Exp $");
#endif #endif
#define MKSH_VERSION "R39 2011/04/22" #define MKSH_VERSION "R39 2011/05/02"
#ifndef MKSH_INCLUDES_ONLY #ifndef MKSH_INCLUDES_ONLY
@ -1749,7 +1749,10 @@ char *snptreef(char *, int, const char *, ...);
struct op *tcopy(struct op *, Area *); struct op *tcopy(struct op *, Area *);
char *wdcopy(const char *, Area *); char *wdcopy(const char *, Area *);
const char *wdscan(const char *, int); const char *wdscan(const char *, int);
char *wdstrip(const char *, bool, bool); #define WDS_TPUTS BIT(0) /* tputS (dumpwdvar) mode */
#define WDS_KEEPQ BIT(1) /* keep quote characters */
#define WDS_MAGIC BIT(2) /* make MAGIC */
char *wdstrip(const char *, int);
void tfree(struct op *, Area *); void tfree(struct op *, Area *);
void dumpchar(struct shf *, int); void dumpchar(struct shf *, int);
void dumptree(struct shf *, struct op *); void dumptree(struct shf *, struct op *);

4
syn.c
View File

@ -22,7 +22,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.61 2011/04/22 12:15:42 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.62 2011/05/02 22:52:53 tg Exp $");
extern short subshell_nesting_level; extern short subshell_nesting_level;
@ -629,7 +629,7 @@ function_body(char *name,
struct op *t; struct op *t;
bool old_func_parse; bool old_func_parse;
sname = wdstrip(name, false, false); sname = wdstrip(name, 0);
/*- /*-
* Check for valid characters in name. POSIX and AT&T ksh93 say * Check for valid characters in name. POSIX and AT&T ksh93 say
* only allow [a-zA-Z_0-9] but this allows more as old pdkshs * only allow [a-zA-Z_0-9] but this allows more as old pdkshs

189
tree.c
View File

@ -22,17 +22,16 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.44 2011/04/22 12:15:42 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.45 2011/05/02 22:52:54 tg Exp $");
#define INDENT 8 #define INDENT 8
static void ptree(struct op *, int, struct shf *); static void ptree(struct op *, int, struct shf *);
static void pioact(struct shf *, int, struct ioword *); static void pioact(struct shf *, int, struct ioword *);
static void tputS(const char *, struct shf *); static const char *wdvarput(struct shf *, const char *, int, int);
static void vfptreef(struct shf *, int, const char *, va_list); static void vfptreef(struct shf *, int, const char *, va_list);
static struct ioword **iocopy(struct ioword **, Area *); static struct ioword **iocopy(struct ioword **, Area *);
static void iofree(struct ioword **, Area *); static void iofree(struct ioword **, Area *);
static void wdstrip_internal(struct shf *, const char *, bool, bool);
/* "foo& ; bar" and "foo |& ; bar" are invalid */ /* "foo& ; bar" and "foo |& ; bar" are invalid */
static bool prevent_semicolon; static bool prevent_semicolon;
@ -265,16 +264,18 @@ pioact(struct shf *shf, int indent, struct ioword *iop)
prevent_semicolon = false; prevent_semicolon = false;
} }
/* variant of fputs for ptreef */ /* variant of fputs for ptreef and wdstrip */
static void static const char *
tputS(const char *wp, struct shf *shf) wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
{ {
int c, quotelevel = 0; int c;
/*- /*-
* problems: * problems:
* `...` -> $(...) * `...` -> $(...)
* 'foo' -> "foo" * 'foo' -> "foo"
* x${foo:-"hi"} -> x${foo:-hi} unless WDS_TPUTS
* x${foo:-'hi'} -> x${foo:-hi} unless WDS_KEEPQ
* could change encoding to: * could change encoding to:
* OQUOTE ["'] ... CQUOTE ["'] * OQUOTE ["'] ... CQUOTE ["']
* COMSUB [(`] ...\0 (handle $ ` \ and maybe " in `...` case) * COMSUB [(`] ...\0 (handle $ ` \ and maybe " in `...` case)
@ -282,18 +283,33 @@ tputS(const char *wp, struct shf *shf)
while (/* CONSTCOND */ 1) while (/* CONSTCOND */ 1)
switch (*wp++) { switch (*wp++) {
case EOS: case EOS:
return; return (wp);
case ADELIM: case ADELIM:
case CHAR: case CHAR:
shf_putchar(*wp++, shf);
break;
case QCHAR:
c = *wp++; c = *wp++;
if (!quotelevel || if ((opmode & WDS_MAGIC) &&
(c == '"' || c == '`' || c == '$' || c == '\\')) (ISMAGIC(c) || c == '[' || c == NOT ||
c == '-' || c == ']' || c == '*' || c == '?'))
shf_putc(MAGIC, shf);
shf_putc(c, shf);
break;
case QCHAR: {
bool doq;
c = *wp++;
doq = (c == '"' || c == '`' || c == '$' || c == '\\');
if (opmode & WDS_TPUTS) {
if (quotelevel == 0)
doq = true;
} else {
if (!(opmode & WDS_KEEPQ))
doq = false;
}
if (doq)
shf_putc('\\', shf); shf_putc('\\', shf);
shf_putc(c, shf); shf_putc(c, shf);
break; break;
}
case COMSUB: case COMSUB:
shf_puts("$(", shf); shf_puts("$(", shf);
while ((c = *wp++) != 0) while ((c = *wp++) != 0)
@ -307,13 +323,17 @@ tputS(const char *wp, struct shf *shf)
shf_puts("))", shf); shf_puts("))", shf);
break; break;
case OQUOTE: case OQUOTE:
quotelevel++; if (opmode & WDS_TPUTS) {
shf_putc('"', shf); quotelevel++;
shf_putc('"', shf);
}
break; break;
case CQUOTE: case CQUOTE:
if (quotelevel) if (opmode & WDS_TPUTS) {
quotelevel--; if (quotelevel)
shf_putc('"', shf); quotelevel--;
shf_putc('"', shf);
}
break; break;
case OSUBST: case OSUBST:
shf_putc('$', shf); shf_putc('$', shf);
@ -321,20 +341,29 @@ tputS(const char *wp, struct shf *shf)
shf_putc('{', shf); shf_putc('{', shf);
while ((c = *wp++) != 0) while ((c = *wp++) != 0)
shf_putc(c, shf); shf_putc(c, shf);
wp = wdvarput(shf, wp, 0, opmode);
break; break;
case CSUBST: case CSUBST:
if (*wp++ == '}') if (*wp++ == '}')
shf_putc('}', shf); shf_putc('}', shf);
break; return (wp);
case OPAT: case OPAT:
shf_putchar(*wp++, shf); if (opmode & WDS_MAGIC) {
shf_putc('(', shf); shf_putc(MAGIC, shf);
shf_putchar(*wp++ | 0x80, shf);
} else {
shf_putchar(*wp++, shf);
shf_putc('(', shf);
}
break; break;
case SPAT: case SPAT:
shf_putc('|', shf); c = '|';
break; if (0)
case CPAT: case CPAT:
shf_putc(')', shf); c = /*(*/ ')';
if (opmode & WDS_MAGIC)
shf_putc(MAGIC, shf);
shf_putc(c, shf);
break; break;
} }
} }
@ -389,7 +418,7 @@ vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
break; break;
case 'S': case 'S':
/* word */ /* word */
tputS(va_arg(va, char *), shf); wdvarput(shf, va_arg(va, char *), 0, WDS_TPUTS);
break; break;
case 'd': case 'd':
/* signed decimal */ /* signed decimal */
@ -569,94 +598,16 @@ wdscan(const char *wp, int c)
* quote characters (" ' \) stripped. (string is allocated from ATEMP) * quote characters (" ' \) stripped. (string is allocated from ATEMP)
*/ */
char * char *
wdstrip(const char *wp, bool keepq, bool make_magic) wdstrip(const char *wp, int opmode)
{ {
struct shf shf; struct shf shf;
shf_sopen(NULL, 32, SHF_WR | SHF_DYNAMIC, &shf); shf_sopen(NULL, 32, SHF_WR | SHF_DYNAMIC, &shf);
wdstrip_internal(&shf, wp, keepq, make_magic); wdvarput(&shf, wp, 0, opmode);
/* shf_sclose NUL terminates */ /* shf_sclose NUL terminates */
return (shf_sclose(&shf)); return (shf_sclose(&shf));
} }
static void
wdstrip_internal(struct shf *shf, const char *wp, bool keepq, bool make_magic)
{
int c;
/*-
* problems:
* `...` -> $(...)
* x${foo:-"hi"} -> x${foo:-hi}
* x${foo:-'hi'} -> x${foo:-hi} unless keepq
*/
while (/* CONSTCOND */ 1)
switch (*wp++) {
case EOS:
return;
case ADELIM:
case CHAR:
c = *wp++;
if (make_magic && (ISMAGIC(c) || c == '[' || c == NOT ||
c == '-' || c == ']' || c == '*' || c == '?'))
shf_putc(MAGIC, shf);
shf_putc(c, shf);
break;
case QCHAR:
c = *wp++;
if (keepq && (c == '"' || c == '`' || c == '$' || c == '\\'))
shf_putc('\\', shf);
shf_putc(c, shf);
break;
case COMSUB:
shf_puts("$(", shf);
while ((c = *wp++) != 0)
shf_putc(c, shf);
shf_putc(')', shf);
break;
case EXPRSUB:
shf_puts("$((", shf);
while (*wp != 0)
shf_putchar(*wp++, shf);
shf_puts("))", shf);
break;
case OQUOTE:
break;
case CQUOTE:
break;
case OSUBST:
shf_putc('$', shf);
if (*wp++ == '{')
shf_putc('{', shf);
while ((c = *wp++) != 0)
shf_putc(c, shf);
break;
case CSUBST:
if (*wp++ == '}')
shf_putc('}', shf);
break;
case OPAT:
if (make_magic) {
shf_putc(MAGIC, shf);
shf_putchar(*wp++ | 0x80, shf);
} else {
shf_putchar(*wp++, shf);
shf_putc('(', shf);
}
break;
case SPAT:
if (make_magic)
shf_putc(MAGIC, shf);
shf_putc('|', shf);
break;
case CPAT:
if (make_magic)
shf_putc(MAGIC, shf);
shf_putc(')', shf);
break;
}
}
static struct ioword ** static struct ioword **
iocopy(struct ioword **iow, Area *ap) iocopy(struct ioword **iow, Area *ap)
{ {
@ -793,29 +744,28 @@ dumpchar(struct shf *shf, int c)
shf_putc(c, shf); shf_putc(c, shf);
} }
/* see: tputS */ /* see: wdvarput */
void static const char *
dumpwdvar(struct shf *shf, const char *wp) dumpwdvar_(struct shf *shf, const char *wp, int quotelevel)
{ {
int c, quotelevel = 0; int c;
while (/* CONSTCOND */ 1) { while (/* CONSTCOND */ 1) {
switch(*wp++) { switch(*wp++) {
case EOS: case EOS:
shf_puts("EOS", shf); shf_puts("EOS", shf);
return; return (wp);
case ADELIM: case ADELIM:
shf_puts("ADELIM=", shf); shf_puts("ADELIM=", shf);
dumpchar: if (0)
case CHAR:
shf_puts("CHAR=", shf);
dumpchar(shf, *wp++); dumpchar(shf, *wp++);
break; break;
case CHAR:
shf_puts("CHAR=", shf);
goto dumpchar;
case QCHAR: case QCHAR:
shf_puts("QCHAR<", shf); shf_puts("QCHAR<", shf);
c = *wp++; c = *wp++;
if (!quotelevel || if (quotelevel == 0 ||
(c == '"' || c == '`' || c == '$' || c == '\\')) (c == '"' || c == '`' || c == '$' || c == '\\'))
shf_putc('\\', shf); shf_putc('\\', shf);
dumpchar(shf, c); dumpchar(shf, c);
@ -847,12 +797,14 @@ dumpwdvar(struct shf *shf, const char *wp)
shf_puts(")[", shf); shf_puts(")[", shf);
while ((c = *wp++) != 0) while ((c = *wp++) != 0)
dumpchar(shf, c); dumpchar(shf, c);
shf_putc('|', shf);
wp = dumpwdvar_(shf, wp, 0);
break; break;
case CSUBST: case CSUBST:
shf_puts("]CSUBST(", shf); shf_puts("]CSUBST(", shf);
dumpchar(shf, *wp++); dumpchar(shf, *wp++);
shf_putc(')', shf); shf_putc(')', shf);
break; return (wp);
case OPAT: case OPAT:
shf_puts("OPAT=", shf); shf_puts("OPAT=", shf);
dumpchar(shf, *wp++); dumpchar(shf, *wp++);
@ -870,6 +822,11 @@ dumpwdvar(struct shf *shf, const char *wp)
shf_putc(' ', shf); shf_putc(' ', shf);
} }
} }
void
dumpwdvar(struct shf *shf, const char *wp)
{
dumpwdvar_(shf, wp, 0);
}
void void
dumptree(struct shf *shf, struct op *t) dumptree(struct shf *shf, struct op *t)