summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Src/builtin.c2
-rw-r--r--Src/subst.c6
-rw-r--r--Src/utils.c39
-rw-r--r--Src/zsh.h6
5 files changed, 45 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index 7fd3d0c1e..e2f427227 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
2010-05-27 Peter Stephenson <p.w.stephenson@ntlworld.com>
+ * 27965 plus as per 27966: Src/builtin.c, Src/subst.c,
+ Src/utils.c, Src/zsh.h: Use $'\n' quoting instead of literal
+ newline for ${(q)...} to avoid lines getting split unexpectedly.
+ Quote empty strings as ''.
+
* 27976: Doc/Zsh/expn.yo: add yet more to the my-brain-hurts
description of how parameter expansion is ordered.
@@ -13164,5 +13169,5 @@
*****************************************************
* This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.4983 $
+* $Revision: 1.4984 $
*****************************************************
diff --git a/Src/builtin.c b/Src/builtin.c
index 3f26f0304..e9e8e3bff 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -4233,7 +4233,7 @@ bin_print(char *name, char **args, Options ops, int func)
break;
case 'q':
stringval = curarg ?
- quotestring(curarg, NULL, QT_BACKSLASH) : &nullstr;
+ quotestring(curarg, NULL, QT_BACKSLASH_SHOWNULL) : &nullstr;
*d = 's';
print_val(stringval);
break;
diff --git a/Src/subst.c b/Src/subst.c
index 80a56410a..304add6f9 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -2896,7 +2896,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
}
} else
for (; *ap; ap++)
- *ap = quotestring(*ap, NULL, QT_BACKSLASH);
+ *ap = quotestring(*ap, NULL, QT_BACKSLASH_SHOWNULL);
} else {
int one = noerrs, oef = errflag, haserr = 0;
@@ -2933,7 +2933,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
if (quotetype == QT_DOLLARS)
val[0] = '$';
} else
- val = quotestring(val, NULL, QT_BACKSLASH);
+ val = quotestring(val, NULL, QT_BACKSLASH_SHOWNULL);
} else {
int one = noerrs, oef = errflag, haserr;
@@ -3490,7 +3490,7 @@ modify(char **str, char **ptr)
subst(&copy, hsubl, hsubr, gbal);
break;
case 'q':
- copy = quotestring(copy, NULL, QT_BACKSLASH);
+ copy = quotestring(copy, NULL, QT_BACKSLASH_SHOWNULL);
break;
case 'Q':
{
diff --git a/Src/utils.c b/Src/utils.c
index 1d7b3109a..184b2f354 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -4576,7 +4576,7 @@ quotestring(const char *s, char **e, int instring)
char *v;
int alloclen;
char *buf;
- int sf = 0;
+ int sf = 0, shownull;
/*
* quotesub is used with QT_SINGLE_OPTIONAL.
* quotesub = 0: mechanism not active
@@ -4585,11 +4585,18 @@ quotestring(const char *s, char **e, int instring)
* quotesub = 2: mechanism active, added opening "'"; need
* closing "'".
*/
- int quotesub = 0;
+ int quotesub = 0, slen;
char *quotestart;
convchar_t cc;
const char *uend;
+ slen = strlen(s);
+ if (instring == QT_BACKSLASH_SHOWNULL) {
+ shownull = 1;
+ instring = QT_BACKSLASH;
+ } else {
+ shownull = 0;
+ }
switch (instring)
{
case QT_BACKSLASH:
@@ -4598,21 +4605,24 @@ quotestring(const char *s, char **e, int instring)
* Keep memory usage within limits by allocating temporary
* storage and using heap for correct size at end.
*/
- alloclen = strlen(s) * 7 + 1;
+ alloclen = slen * 7 + 1;
+ if (!*s && shownull)
+ alloclen += 2; /* for '' */
break;
case QT_SINGLE_OPTIONAL:
/*
* Here, we may need to add single quotes.
*/
- alloclen = strlen(s) * 4 + 3;
+ alloclen = slen * 4 + 3;
quotesub = 1;
break;
default:
- alloclen = strlen(s) * 4 + 1;
+ alloclen = slen * 4 + 1;
break;
}
+
tt = quotestart = v = buf = zshcalloc(alloclen);
DPUTS(instring < QT_BACKSLASH || instring == QT_BACKTICK ||
@@ -4659,6 +4669,13 @@ quotestring(const char *s, char **e, int instring)
}
else
{
+ if (shownull) {
+ /* We can't show an empty string with just backslash quoting. */
+ if (!*u) {
+ *v++ = '\'';
+ *v++ = '\'';
+ }
+ }
/*
* Here there are syntactic special characters, so
* we start by going through bytewise.
@@ -4771,15 +4788,19 @@ quotestring(const char *s, char **e, int instring)
continue;
} else if (*u == '\n' ||
(instring == QT_SINGLE && *u == '\'')) {
- if (unset(RCQUOTES)) {
+ if (*u == '\n') {
+ *v++ = '$';
+ *v++ = '\'';
+ *v++ = '\\';
+ *v++ = 'n';
+ *v++ = '\'';
+ } else if (unset(RCQUOTES)) {
*v++ = '\'';
if (*u == '\'')
*v++ = '\\';
*v++ = *u;
*v++ = '\'';
- } else if (*u == '\n')
- *v++ = '"', *v++ = '\n', *v++ = '"';
- else
+ } else
*v++ = '\'', *v++ = '\'';
u++;
continue;
diff --git a/Src/zsh.h b/Src/zsh.h
index 1b1175cb2..77281aa75 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -218,7 +218,11 @@ enum {
* Single quotes, but the default is not to quote unless necessary.
* This is only useful as an argument to quotestring().
*/
- QT_SINGLE_OPTIONAL
+ QT_SINGLE_OPTIONAL,
+ /*
+ * As QT_BACKSLASH, but a NULL string is shown as ''.
+ */
+ QT_BACKSLASH_SHOWNULL
};
#define QT_IS_SINGLE(x) ((x) == QT_SINGLE || (x) == QT_SINGLE_OPTIONAL)