mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-02 10:01:11 +02:00
22575: multibyte fixes for bslashquote(), getzlequery()
This commit is contained in:
parent
7d77bc95b2
commit
bb912594b2
6 changed files with 170 additions and 155 deletions
|
@ -1861,7 +1861,7 @@ asklist(void)
|
|||
listdat.nlines));
|
||||
qup = ((l + columns - 1) / columns) - 1;
|
||||
fflush(shout);
|
||||
if (getzlequery(1) != 'y') {
|
||||
if (!getzlequery()) {
|
||||
if (clearflag) {
|
||||
putc('\r', shout);
|
||||
tcmultout(TCUP, TCMULTUP, qup);
|
||||
|
|
|
@ -125,9 +125,9 @@ static inline int ZS_strncmp(ZLE_STRING_T s1, ZLE_STRING_T s2, size_t l)
|
|||
#define ZC_icntrl icntrl
|
||||
#define ZC_idigit idigit
|
||||
#define ZC_iident iident
|
||||
#define ZC_ilower ilower
|
||||
#define ZC_ilower islower
|
||||
#define ZC_inblank inblank
|
||||
#define ZC_iupper iupper
|
||||
#define ZC_iupper isupper
|
||||
#define ZC_iword iword
|
||||
|
||||
#define ZC_tolower tulower
|
||||
|
|
|
@ -2298,7 +2298,7 @@ listlist(LinkList l)
|
|||
fprintf(shout, "zsh: do you wish to see all %d lines? ", nlines));
|
||||
qup = ((l + columns - 1) / columns) - 1;
|
||||
fflush(shout);
|
||||
if (getzlequery(1) != 'y') {
|
||||
if (!getzlequery()) {
|
||||
if (clearflag) {
|
||||
putc('\r', shout);
|
||||
tcmultout(TCUP, TCMULTUP, qup);
|
||||
|
|
|
@ -653,50 +653,42 @@ zlinefind(ZLE_STRING_T haystack, int haylen, int pos,
|
|||
}
|
||||
|
||||
/*
|
||||
* Query the user, and return a single character response. The question
|
||||
* is assumed to have been printed already, and the cursor is left
|
||||
* immediately after the response echoed. (Might cause a problem if
|
||||
* this takes it onto the next line.) If yesno is non-zero: <Tab> is
|
||||
* interpreted as 'y'; any other control character is interpreted as
|
||||
* 'n'. If there are any characters in the buffer, this is taken as a
|
||||
* negative response, and no characters are read. Case is folded.
|
||||
*
|
||||
* TBD: this may need extending to return a wchar_t or possibly
|
||||
* a wint_t.
|
||||
* Query the user, and return 1 for yes, 0 for no. The question is assumed to
|
||||
* have been printed already, and the cursor is left immediately after the
|
||||
* response echoed. (Might cause a problem if this takes it onto the next
|
||||
* line.) <Tab> is interpreted as 'y'; any other control character is
|
||||
* interpreted as 'n'. If there are any characters in the buffer, this is
|
||||
* taken as a negative response, and no characters are read. Case is folded.
|
||||
*/
|
||||
|
||||
/**/
|
||||
mod_export int
|
||||
getzlequery(int yesno)
|
||||
getzlequery(void)
|
||||
{
|
||||
ZLE_INT_T c;
|
||||
#ifdef FIONREAD
|
||||
int val;
|
||||
|
||||
if (yesno) {
|
||||
/* check for typeahead, which is treated as a negative response */
|
||||
ioctl(SHTTY, FIONREAD, (char *)&val);
|
||||
if (val) {
|
||||
putc('n', shout);
|
||||
return 'n';
|
||||
}
|
||||
/* check for typeahead, which is treated as a negative response */
|
||||
ioctl(SHTTY, FIONREAD, (char *)&val);
|
||||
if (val) {
|
||||
putc('n', shout);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get a character from the tty and interpret it */
|
||||
c = getfullchar(0);
|
||||
if (yesno) {
|
||||
if (c == ZWC('\t'))
|
||||
c = ZWC('y');
|
||||
else if (ZC_icntrl(c) || c == ZLEEOF)
|
||||
c = ZWC('n');
|
||||
else
|
||||
c = ZC_tolower(c);
|
||||
}
|
||||
if (c == ZWC('\t'))
|
||||
c = ZWC('y');
|
||||
else if (ZC_icntrl(c) || c == ZLEEOF)
|
||||
c = ZWC('n');
|
||||
else
|
||||
c = ZC_tolower(c);
|
||||
/* echo response and return */
|
||||
if (c != ZWC('\n'))
|
||||
zwcputc(c);
|
||||
return c;
|
||||
return c == ZWC('y');
|
||||
}
|
||||
|
||||
/* Format a string, keybinding style. */
|
||||
|
|
264
Src/utils.c
264
Src/utils.c
|
@ -2835,7 +2835,7 @@ wcsitype(wchar_t c, int itype)
|
|||
if (len == 0) {
|
||||
/* NULL is special */
|
||||
return zistype(0, itype);
|
||||
} else if (len == 1 && iascii(*outstr)) {
|
||||
} else if (len == 1 && isascii(*outstr)) {
|
||||
return zistype(*outstr, itype);
|
||||
} else {
|
||||
switch (itype) {
|
||||
|
@ -2897,7 +2897,7 @@ itype_end(const char *ptr, int itype, int once)
|
|||
/* in this case non-ASCII characters can't match */
|
||||
if (chr > 127 || !zistype(chr,itype))
|
||||
break;
|
||||
} else if (len == 1 && iascii(*ptr)) {
|
||||
} else if (len == 1 && isascii(*ptr)) {
|
||||
/* ASCII: can't be metafied, use standard test */
|
||||
if (!zistype(*ptr,itype))
|
||||
break;
|
||||
|
@ -4017,7 +4017,7 @@ hasspecial(char const *s)
|
|||
* The last argument should be zero if this is to be used outside a string, *
|
||||
* one if it is to be quoted for the inside of a single quoted string, *
|
||||
* two if it is for the inside of a double quoted string, and *
|
||||
* three if it is for the inside of a posix quoted string. *
|
||||
* three if it is for the inside of a $'...' quoted string. *
|
||||
* The string may be metafied and contain tokens. */
|
||||
|
||||
/**/
|
||||
|
@ -4031,127 +4031,153 @@ bslashquote(const char *s, char **e, int instring)
|
|||
|
||||
tt = v = buf;
|
||||
u = s;
|
||||
for (; *u; u++) {
|
||||
if (e && *e == u)
|
||||
*e = v, sf = 1;
|
||||
if (instring == 3) {
|
||||
int c = *u;
|
||||
if (c == Meta) {
|
||||
c = *++u ^ 32;
|
||||
}
|
||||
c &= 0xff;
|
||||
if(isprint(c)) {
|
||||
switch (c) {
|
||||
case '\\':
|
||||
case '\'':
|
||||
*v++ = '\\';
|
||||
*v++ = c;
|
||||
break;
|
||||
if (instring == 3) {
|
||||
/*
|
||||
* 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);
|
||||
|
||||
default:
|
||||
if(imeta(c)) {
|
||||
*v++ = Meta;
|
||||
*v++ = c ^ 32;
|
||||
}
|
||||
else {
|
||||
if (isset(BANGHIST) && c == bangchar) {
|
||||
*v++ = '\\';
|
||||
}
|
||||
*v++ = c;
|
||||
}
|
||||
break;
|
||||
if (e && !sf && *e <= u) {
|
||||
*e = v;
|
||||
sf = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (c) {
|
||||
case '\0':
|
||||
*v++ = '\\';
|
||||
*v++ = '0';
|
||||
if ('0' <= u[1] && u[1] <= '7') {
|
||||
*v++ = '0';
|
||||
*v++ = '0';
|
||||
}
|
||||
break;
|
||||
if (
|
||||
#ifdef MULTIBYTE_SUPPORT
|
||||
cc != WEOF &&
|
||||
#endif
|
||||
MB_ISPRINT(cc)) {
|
||||
switch (cc) {
|
||||
case ZWC('\\'):
|
||||
case ZWC('\''):
|
||||
*v++ = '\\';
|
||||
break;
|
||||
|
||||
case '\007': *v++ = '\\'; *v++ = 'a'; break;
|
||||
case '\b': *v++ = '\\'; *v++ = 'b'; break;
|
||||
case '\f': *v++ = '\\'; *v++ = 'f'; break;
|
||||
case '\n': *v++ = '\\'; *v++ = 'n'; break;
|
||||
case '\r': *v++ = '\\'; *v++ = 'r'; break;
|
||||
case '\t': *v++ = '\\'; *v++ = 't'; break;
|
||||
case '\v': *v++ = '\\'; *v++ = 'v'; break;
|
||||
|
||||
default:
|
||||
*v++ = '\\';
|
||||
*v++ = '0' + ((c >> 6) & 7);
|
||||
*v++ = '0' + ((c >> 3) & 7);
|
||||
*v++ = '0' + (c & 7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (*u == Tick || *u == Qtick) {
|
||||
char c = *u++;
|
||||
|
||||
*v++ = c;
|
||||
while (*u && *u != c)
|
||||
*v++ = *u++;
|
||||
*v++ = c;
|
||||
if (!*u)
|
||||
u--;
|
||||
continue;
|
||||
}
|
||||
else if ((*u == String || *u == Qstring) &&
|
||||
(u[1] == Inpar || u[1] == Inbrack || u[1] == Inbrace)) {
|
||||
char c = (u[1] == Inpar ? Outpar : (u[1] == Inbrace ?
|
||||
Outbrace : Outbrack));
|
||||
char beg = *u;
|
||||
int level = 0;
|
||||
|
||||
*v++ = *u++;
|
||||
*v++ = *u++;
|
||||
while (*u && (*u != c || level)) {
|
||||
if (*u == beg)
|
||||
level++;
|
||||
else if (*u == c)
|
||||
level--;
|
||||
*v++ = *u++;
|
||||
}
|
||||
if (*u)
|
||||
*v++ = *u;
|
||||
else
|
||||
u--;
|
||||
continue;
|
||||
}
|
||||
else if (ispecial(*u) &&
|
||||
((*u != '=' && *u != '~') ||
|
||||
u == s ||
|
||||
(isset(MAGICEQUALSUBST) && (u[-1] == '=' || u[-1] == ':')) ||
|
||||
(*u == '~' && isset(EXTENDEDGLOB))) &&
|
||||
(!instring ||
|
||||
(isset(BANGHIST) && *u == (char)bangchar && instring != 1) ||
|
||||
(instring == 2 &&
|
||||
(*u == '$' || *u == '`' || *u == '\"' || *u == '\\')) ||
|
||||
(instring == 1 && *u == '\''))) {
|
||||
if (*u == '\n' || (instring == 1 && *u == '\'')) {
|
||||
if (unset(RCQUOTES)) {
|
||||
*v++ = '\'';
|
||||
if (*u == '\'')
|
||||
default:
|
||||
if (isset(BANGHIST) && cc == (wchar_t)bangchar)
|
||||
*v++ = '\\';
|
||||
*v++ = *u;
|
||||
*v++ = '\'';
|
||||
} else if (*u == '\n')
|
||||
*v++ = '"', *v++ = '\n', *v++ = '"';
|
||||
else
|
||||
*v++ = '\'', *v++ = '\'';
|
||||
continue;
|
||||
} else
|
||||
*v++ = '\\';
|
||||
break;
|
||||
}
|
||||
while (u < uend)
|
||||
*v++ = *u++;
|
||||
} else {
|
||||
/* Not printable */
|
||||
for (; u < uend; u++) {
|
||||
/*
|
||||
* Just do this byte by byte; there's no great
|
||||
* advantage in being clever with multibyte
|
||||
* characters if we don't think they're printable.
|
||||
*/
|
||||
int c;
|
||||
if (*u == Meta)
|
||||
c = STOUC(*++u ^ 32);
|
||||
else
|
||||
c = STOUC(*u);
|
||||
switch (c) {
|
||||
case '\0':
|
||||
*v++ = '\\';
|
||||
*v++ = '0';
|
||||
if ('0' <= u[1] && u[1] <= '7') {
|
||||
*v++ = '0';
|
||||
*v++ = '0';
|
||||
}
|
||||
break;
|
||||
|
||||
case '\007': *v++ = '\\'; *v++ = 'a'; break;
|
||||
case '\b': *v++ = '\\'; *v++ = 'b'; break;
|
||||
case '\f': *v++ = '\\'; *v++ = 'f'; break;
|
||||
case '\n': *v++ = '\\'; *v++ = 'n'; break;
|
||||
case '\r': *v++ = '\\'; *v++ = 'r'; break;
|
||||
case '\t': *v++ = '\\'; *v++ = 't'; break;
|
||||
case '\v': *v++ = '\\'; *v++ = 'v'; break;
|
||||
|
||||
default:
|
||||
*v++ = '\\';
|
||||
*v++ = '0' + ((c >> 6) & 7);
|
||||
*v++ = '0' + ((c >> 3) & 7);
|
||||
*v++ = '0' + (c & 7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Here the only special characters are syntactic, so
|
||||
* we can go through bytewise.
|
||||
*/
|
||||
for (; *u; u++) {
|
||||
if (e && *e == u)
|
||||
*e = v, sf = 1;
|
||||
if (*u == Tick || *u == Qtick) {
|
||||
char c = *u++;
|
||||
|
||||
*v++ = c;
|
||||
while (*u && *u != c)
|
||||
*v++ = *u++;
|
||||
*v++ = c;
|
||||
if (!*u)
|
||||
u--;
|
||||
continue;
|
||||
}
|
||||
else if ((*u == String || *u == Qstring) &&
|
||||
(u[1] == Inpar || u[1] == Inbrack || u[1] == Inbrace)) {
|
||||
char c = (u[1] == Inpar ? Outpar : (u[1] == Inbrace ?
|
||||
Outbrace : Outbrack));
|
||||
char beg = *u;
|
||||
int level = 0;
|
||||
|
||||
*v++ = *u++;
|
||||
*v++ = *u++;
|
||||
while (*u && (*u != c || level)) {
|
||||
if (*u == beg)
|
||||
level++;
|
||||
else if (*u == c)
|
||||
level--;
|
||||
*v++ = *u++;
|
||||
}
|
||||
if (*u)
|
||||
*v++ = *u;
|
||||
else
|
||||
u--;
|
||||
continue;
|
||||
}
|
||||
else if (ispecial(*u) &&
|
||||
((*u != '=' && *u != '~') ||
|
||||
u == s ||
|
||||
(isset(MAGICEQUALSUBST) &&
|
||||
(u[-1] == '=' || u[-1] == ':')) ||
|
||||
(*u == '~' && isset(EXTENDEDGLOB))) &&
|
||||
(!instring ||
|
||||
(isset(BANGHIST) && *u == (char)bangchar &&
|
||||
instring != 1) ||
|
||||
(instring == 2 &&
|
||||
(*u == '$' || *u == '`' || *u == '\"' || *u == '\\')) ||
|
||||
(instring == 1 && *u == '\''))) {
|
||||
if (*u == '\n' || (instring == 1 && *u == '\'')) {
|
||||
if (unset(RCQUOTES)) {
|
||||
*v++ = '\'';
|
||||
if (*u == '\'')
|
||||
*v++ = '\\';
|
||||
*v++ = *u;
|
||||
*v++ = '\'';
|
||||
} else if (*u == '\n')
|
||||
*v++ = '"', *v++ = '\n', *v++ = '"';
|
||||
else
|
||||
*v++ = '\'', *v++ = '\'';
|
||||
continue;
|
||||
} else
|
||||
*v++ = '\\';
|
||||
}
|
||||
if(*u == Meta)
|
||||
*v++ = *u++;
|
||||
*v++ = *u;
|
||||
}
|
||||
if(*u == Meta)
|
||||
*v++ = *u++;
|
||||
*v++ = *u;
|
||||
}
|
||||
*v = '\0';
|
||||
|
||||
|
|
|
@ -61,11 +61,8 @@
|
|||
|
||||
#ifdef MULTIBYTE_SUPPORT
|
||||
#define MB_ZISTYPE(X,Y) wcsitype((X),(Y))
|
||||
#define MB_ISPRINT(X) iswprint(X)
|
||||
#else
|
||||
#define MB_ZISTYPE(X,Y) zistype((X),(Y))
|
||||
#define MB_ISPRINT(X) isprint(X)
|
||||
#endif
|
||||
|
||||
#define iascii(X) isascii(STOUC(X))
|
||||
#define ilower(X) islower(STOUC(X))
|
||||
#define iprint(X) isprint(STOUC(X))
|
||||
#define iupper(X) isupper(STOUC(X))
|
||||
|
|
Loading…
Reference in a new issue