1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-01-21 00:01:26 +01:00

23784: Use $'\...' for quoting unparseable characters

This commit is contained in:
Peter Stephenson 2007-08-20 21:22:18 +00:00
parent 53184f457b
commit bfa48687c0
2 changed files with 112 additions and 53 deletions

View file

@ -1,3 +1,8 @@
2007-08-20 Peter Stephenson <p.w.stephenson@ntlworld.com>
* 23784: Src/utils.c: Use $'\...' quoting for unparseable and
unprintable characters when doing backslash quoting.
2007-08-19 Clint Adams <clint@zsh.org>
* R.Ramkumar: 23783: Completion/Zsh/Command/_command,

View file

@ -4124,65 +4124,10 @@ hasspecial(char const *s)
return 0;
}
/*
* Quote the string s and return the result.
*
* If e is non-zero, the
* pointer it points to may point to a position in s and in e the position
* of the corresponding character in the quoted string is returned.
*
* The last argument is a QT_ value defined in zsh.h other than QT_NONE.
*
* The string may be metafied and contain tokens.
*/
/**/
mod_export char *
quotestring(const char *s, char **e, int instring)
static char *
addunprintable(char *v, const char *u, const char *uend)
{
const char *u, *tt;
char *v;
char *buf = hcalloc(4 * strlen(s) + 1);
int sf = 0;
DPUTS(instring < QT_BACKSLASH || instring > QT_DOLLARS,
"BUG: bad quote type in quotestring");
tt = v = buf;
u = s;
if (instring == QT_DOLLARS) {
/*
* As we test for printability here we need to be able
* to look for multibyte characters.
*/
convchar_t cc;
MB_METACHARINIT();
while (*u) {
const char *uend = u + MB_METACHARLENCONV(u, &cc);
if (e && !sf && *e <= u) {
*e = v;
sf = 1;
}
if (
#ifdef MULTIBYTE_SUPPORT
cc != WEOF &&
#endif
WC_ISPRINT(cc)) {
switch (cc) {
case ZWC('\\'):
case ZWC('\''):
*v++ = '\\';
break;
default:
if (isset(BANGHIST) && cc == (wchar_t)bangchar)
*v++ = '\\';
break;
}
while (u < uend)
*v++ = *u++;
} else {
/* Not printable */
for (; u < uend; u++) {
/*
* Just do this byte by byte; there's no great
@ -4220,16 +4165,89 @@ quotestring(const char *s, char **e, int instring)
break;
}
}
return v;
}
/*
* Quote the string s and return the result.
*
* If e is non-zero, the
* pointer it points to may point to a position in s and in e the position
* of the corresponding character in the quoted string is returned.
*
* The last argument is a QT_ value defined in zsh.h other than QT_NONE.
*
* The string may be metafied and contain tokens.
*/
/**/
mod_export char *
quotestring(const char *s, char **e, int instring)
{
const char *u, *tt;
char *v;
/*
* With QT_BACKSLASH we may need to use $'\300' stuff.
* Keep memory usage within limits by allocating temporary
* storage and using heap for correct size at end.
*/
int alloclen = (instring == QT_BACKSLASH ? 7 : 4) * strlen(s) + 1;
char *buf = zshcalloc(alloclen);
int sf = 0;
convchar_t cc;
const char *uend;
DPUTS(instring < QT_BACKSLASH || instring > QT_DOLLARS,
"BUG: bad quote type in quotestring");
tt = v = buf;
u = s;
if (instring == QT_DOLLARS) {
/*
* As we test for printability here we need to be able
* to look for multibyte characters.
*/
MB_METACHARINIT();
while (*u) {
uend = u + MB_METACHARLENCONV(u, &cc);
if (e && !sf && *e <= u) {
*e = v;
sf = 1;
}
if (
#ifdef MULTIBYTE_SUPPORT
cc != WEOF &&
#endif
WC_ISPRINT(cc)) {
switch (cc) {
case ZWC('\\'):
case ZWC('\''):
*v++ = '\\';
break;
default:
if (isset(BANGHIST) && cc == (wchar_t)bangchar)
*v++ = '\\';
break;
}
while (u < uend)
*v++ = *u++;
} else {
/* Not printable */
v = addunprintable(v, u, uend);
u = uend;
}
}
}
else
{
/*
* Here the only special characters are syntactic, so
* we can go through bytewise.
* Here there are syntactic special characters, so
* we start by going through bytewise.
*/
for (; *u; u++) {
while (*u) {
int dobackslash = 0;
if (e && *e == u)
*e = v, sf = 1;
if (*u == Tick || *u == Qtick) {
@ -4239,8 +4257,6 @@ quotestring(const char *s, char **e, int instring)
while (*u && *u != c)
*v++ = *u++;
*v++ = c;
if (!*u)
u--;
continue;
} else if ((*u == Qstring || *u == '$') && u[1] == '\'' &&
instring == QT_DOUBLE) {
@ -4268,9 +4284,7 @@ quotestring(const char *s, char **e, int instring)
*v++ = *u++;
}
if (*u)
*v++ = *u;
else
u--;
*v++ = *u++;
continue;
}
else if (ispecial(*u) &&
@ -4296,13 +4310,51 @@ quotestring(const char *s, char **e, int instring)
*v++ = '"', *v++ = '\n', *v++ = '"';
else
*v++ = '\'', *v++ = '\'';
u++;
continue;
} else
*v++ = '\\';
} else {
/*
* We'll need a backslash, but don't add it
* yet since if the character isn't printable
* we'll have to upgrade it to $'...'.
*/
dobackslash = 1;
}
}
if (itok(*u) || instring != QT_BACKSLASH) {
/* Needs to be passed straight through. */
if (dobackslash)
*v++ = '\\';
*v++ = *u++;
continue;
}
/*
* Now check if the output is unprintable in the
* current character set.
*/
uend = u + MB_METACHARLENCONV(u, &cc);
if (
#ifdef MULTIBYTE_SUPPORT
cc != WEOF &&
#endif
WC_ISPRINT(cc)) {
if (dobackslash)
*v++ = '\\';
while (u < uend) {
if (*u == Meta)
*v++ = *u++;
*v++ = *u;
*v++ = *u++;
}
} else {
/* Not printable */
*v++ = '$';
*v++ = '\'';
v = addunprintable(v, u, uend);
*v++ = '\'';
u = uend;
}
}
}
*v = '\0';
@ -4311,7 +4363,9 @@ quotestring(const char *s, char **e, int instring)
*e = v, sf = 1;
DPUTS(e && !sf, "BUG: Wild pointer *e in quotestring()");
return buf;
v = dupstring(buf);
zfree(buf, alloclen);
return v;
}
/* Unmetafy and output a string, quoted if it contains special characters. */