From 69f98bca9ad0fd170caf6f1fd887a8b1eeebb212 Mon Sep 17 00:00:00 2001 From: tg Date: Mon, 2 May 2011 22:52:54 +0000 Subject: [PATCH] =?UTF-8?q?=E2=80=A2=20fix=20wtf(1)=20by=20keeping=20the?= =?UTF-8?q?=20paren=20in=20${foo#\(}=20properly=20escaped=20in=20COMSUB=20?= =?UTF-8?q?=E2=80=A2=20merge=20tputS=20and=20wdstrip=5Finternal=20?= =?UTF-8?q?=E2=87=92=20net=20save:=20604=20.text=200=20.data=200=20.bss=20?= =?UTF-8?q?(MirBSD/i386)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- check.t | 18 +++--- eval.c | 11 ++-- lex.c | 4 +- sh.h | 9 ++- syn.c | 4 +- tree.c | 189 ++++++++++++++++++++++---------------------------------- 6 files changed, 98 insertions(+), 137 deletions(-) diff --git a/check.t b/check.t index 67cb6cc..0fd7005 100644 --- a/check.t +++ b/check.t @@ -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: 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 $ @@ -25,7 +25,7 @@ # http://www.research.att.com/~gsf/public/ifs.sh expected-stdout: - @(#)MIRBSD KSH R39 2011/04/22 + @(#)MIRBSD KSH R39 2011/05/02 description: Check version of shell. stdin: @@ -7392,7 +7392,7 @@ stdin: echo "fo\ob\"a\`r\'b\$az" echo 'fo\ob\"a\`r'\''b\$az' #OSUBST_CSUBST_OPAT_SPAT_CPAT - [[ ${foo#blub} = @(bar|baz) ]] + [[ ${foo#bl\(u\)b} = @(bar|baz) ]] #heredoc_closed x=$(cat <areap); s->start = s->str = s->u.freeme = dp; s->next = source; diff --git a/sh.h b/sh.h index f8e4bec..f5b3849 100644 --- a/sh.h +++ b/sh.h @@ -151,9 +151,9 @@ #endif #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 -#define MKSH_VERSION "R39 2011/04/22" +#define MKSH_VERSION "R39 2011/05/02" #ifndef MKSH_INCLUDES_ONLY @@ -1749,7 +1749,10 @@ char *snptreef(char *, int, const char *, ...); struct op *tcopy(struct op *, Area *); char *wdcopy(const char *, Area *); 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 dumpchar(struct shf *, int); void dumptree(struct shf *, struct op *); diff --git a/syn.c b/syn.c index f020dbb..8002644 100644 --- a/syn.c +++ b/syn.c @@ -22,7 +22,7 @@ #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; @@ -629,7 +629,7 @@ function_body(char *name, struct op *t; 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 * only allow [a-zA-Z_0-9] but this allows more as old pdkshs diff --git a/tree.c b/tree.c index a9ad04d..aa99e79 100644 --- a/tree.c +++ b/tree.c @@ -22,17 +22,16 @@ #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 static void ptree(struct op *, int, struct shf *); 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 struct ioword **iocopy(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 */ static bool prevent_semicolon; @@ -265,16 +264,18 @@ pioact(struct shf *shf, int indent, struct ioword *iop) prevent_semicolon = false; } -/* variant of fputs for ptreef */ -static void -tputS(const char *wp, struct shf *shf) +/* variant of fputs for ptreef and wdstrip */ +static const char * +wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode) { - int c, quotelevel = 0; + int c; /*- * problems: * `...` -> $(...) * 'foo' -> "foo" + * x${foo:-"hi"} -> x${foo:-hi} unless WDS_TPUTS + * x${foo:-'hi'} -> x${foo:-hi} unless WDS_KEEPQ * could change encoding to: * OQUOTE ["'] ... CQUOTE ["'] * COMSUB [(`] ...\0 (handle $ ` \ and maybe " in `...` case) @@ -282,18 +283,33 @@ tputS(const char *wp, struct shf *shf) while (/* CONSTCOND */ 1) switch (*wp++) { case EOS: - return; + return (wp); case ADELIM: case CHAR: - shf_putchar(*wp++, shf); - break; - case QCHAR: c = *wp++; - if (!quotelevel || - (c == '"' || c == '`' || c == '$' || c == '\\')) + if ((opmode & WDS_MAGIC) && + (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(c, shf); break; + } case COMSUB: shf_puts("$(", shf); while ((c = *wp++) != 0) @@ -307,13 +323,17 @@ tputS(const char *wp, struct shf *shf) shf_puts("))", shf); break; case OQUOTE: - quotelevel++; - shf_putc('"', shf); + if (opmode & WDS_TPUTS) { + quotelevel++; + shf_putc('"', shf); + } break; case CQUOTE: - if (quotelevel) - quotelevel--; - shf_putc('"', shf); + if (opmode & WDS_TPUTS) { + if (quotelevel) + quotelevel--; + shf_putc('"', shf); + } break; case OSUBST: shf_putc('$', shf); @@ -321,20 +341,29 @@ tputS(const char *wp, struct shf *shf) shf_putc('{', shf); while ((c = *wp++) != 0) shf_putc(c, shf); + wp = wdvarput(shf, wp, 0, opmode); break; case CSUBST: if (*wp++ == '}') shf_putc('}', shf); - break; + return (wp); case OPAT: - shf_putchar(*wp++, shf); - shf_putc('(', shf); + if (opmode & WDS_MAGIC) { + shf_putc(MAGIC, shf); + shf_putchar(*wp++ | 0x80, shf); + } else { + shf_putchar(*wp++, shf); + shf_putc('(', shf); + } break; case SPAT: - shf_putc('|', shf); - break; + c = '|'; + if (0) case CPAT: - shf_putc(')', shf); + c = /*(*/ ')'; + if (opmode & WDS_MAGIC) + shf_putc(MAGIC, shf); + shf_putc(c, shf); break; } } @@ -389,7 +418,7 @@ vfptreef(struct shf *shf, int indent, const char *fmt, va_list va) break; case 'S': /* word */ - tputS(va_arg(va, char *), shf); + wdvarput(shf, va_arg(va, char *), 0, WDS_TPUTS); break; case 'd': /* signed decimal */ @@ -569,94 +598,16 @@ wdscan(const char *wp, int c) * quote characters (" ' \) stripped. (string is allocated from ATEMP) */ char * -wdstrip(const char *wp, bool keepq, bool make_magic) +wdstrip(const char *wp, int opmode) { struct shf 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 */ 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 ** iocopy(struct ioword **iow, Area *ap) { @@ -793,29 +744,28 @@ dumpchar(struct shf *shf, int c) shf_putc(c, shf); } -/* see: tputS */ -void -dumpwdvar(struct shf *shf, const char *wp) +/* see: wdvarput */ +static const char * +dumpwdvar_(struct shf *shf, const char *wp, int quotelevel) { - int c, quotelevel = 0; + int c; while (/* CONSTCOND */ 1) { switch(*wp++) { case EOS: shf_puts("EOS", shf); - return; + return (wp); case ADELIM: shf_puts("ADELIM=", shf); - dumpchar: + if (0) + case CHAR: + shf_puts("CHAR=", shf); dumpchar(shf, *wp++); break; - case CHAR: - shf_puts("CHAR=", shf); - goto dumpchar; case QCHAR: shf_puts("QCHAR<", shf); c = *wp++; - if (!quotelevel || + if (quotelevel == 0 || (c == '"' || c == '`' || c == '$' || c == '\\')) shf_putc('\\', shf); dumpchar(shf, c); @@ -847,12 +797,14 @@ dumpwdvar(struct shf *shf, const char *wp) shf_puts(")[", shf); while ((c = *wp++) != 0) dumpchar(shf, c); + shf_putc('|', shf); + wp = dumpwdvar_(shf, wp, 0); break; case CSUBST: shf_puts("]CSUBST(", shf); dumpchar(shf, *wp++); shf_putc(')', shf); - break; + return (wp); case OPAT: shf_puts("OPAT=", shf); dumpchar(shf, *wp++); @@ -870,6 +822,11 @@ dumpwdvar(struct shf *shf, const char *wp) shf_putc(' ', shf); } } +void +dumpwdvar(struct shf *shf, const char *wp) +{ + dumpwdvar_(shf, wp, 0); +} void dumptree(struct shf *shf, struct op *t)