mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-01 01:20:00 +02:00
commit bash-20090528 snapshot
This commit is contained in:
+12
-1
@@ -733,6 +733,7 @@ rl_redisplay ()
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
/* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
|
||||
wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
|
||||
}
|
||||
else
|
||||
@@ -893,6 +894,7 @@ rl_redisplay ()
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
in += wc_bytes;
|
||||
/* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
|
||||
wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
|
||||
}
|
||||
else
|
||||
@@ -1189,9 +1191,11 @@ rl_redisplay ()
|
||||
if (t < out)
|
||||
line[t - 1] = '>';
|
||||
|
||||
if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
|
||||
if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
|
||||
{
|
||||
forced_display = 0;
|
||||
o_cpos = _rl_last_c_pos;
|
||||
cpos_adjusted = 0;
|
||||
update_line (&visible_line[last_lmargin],
|
||||
&invisible_line[lmargin],
|
||||
0,
|
||||
@@ -1199,6 +1203,13 @@ rl_redisplay ()
|
||||
_rl_screenwidth + (lmargin ? 0 : wrap_offset),
|
||||
0);
|
||||
|
||||
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
|
||||
cpos_adjusted == 0 &&
|
||||
_rl_last_c_pos != o_cpos &&
|
||||
_rl_last_c_pos > wrap_offset &&
|
||||
o_cpos < prompt_last_invisible)
|
||||
_rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
|
||||
|
||||
/* If the visible new line is shorter than the old, but the number
|
||||
of invisible characters is greater, and we are at the end of
|
||||
the new line, we need to clear to eol. */
|
||||
|
||||
+12
-3
@@ -733,6 +733,7 @@ rl_redisplay ()
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
/* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
|
||||
wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
|
||||
}
|
||||
else
|
||||
@@ -893,6 +894,7 @@ rl_redisplay ()
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
in += wc_bytes;
|
||||
/* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
|
||||
wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
|
||||
}
|
||||
else
|
||||
@@ -1189,9 +1191,11 @@ rl_redisplay ()
|
||||
if (t < out)
|
||||
line[t - 1] = '>';
|
||||
|
||||
if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
|
||||
if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
|
||||
{
|
||||
forced_display = 0;
|
||||
o_cpos = _rl_last_c_pos;
|
||||
cpos_adjusted = 0;
|
||||
update_line (&visible_line[last_lmargin],
|
||||
&invisible_line[lmargin],
|
||||
0,
|
||||
@@ -1199,6 +1203,13 @@ rl_redisplay ()
|
||||
_rl_screenwidth + (lmargin ? 0 : wrap_offset),
|
||||
0);
|
||||
|
||||
if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
|
||||
cpos_adjusted == 0 &&
|
||||
_rl_last_c_pos != o_cpos &&
|
||||
_rl_last_c_pos > wrap_offset &&
|
||||
o_cpos < prompt_last_invisible)
|
||||
_rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
|
||||
|
||||
/* If the visible new line is shorter than the old, but the number
|
||||
of invisible characters is greater, and we are at the end of
|
||||
the new line, we need to clear to eol. */
|
||||
@@ -1895,10 +1906,8 @@ _rl_move_cursor_relative (new, data)
|
||||
woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
|
||||
cpos = _rl_last_c_pos;
|
||||
|
||||
#if 0
|
||||
if (cpos == 0 && cpos == new)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* If we have multibyte characters, NEW is indexed by the buffer point in
|
||||
|
||||
@@ -77,7 +77,7 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
|
||||
char *string;
|
||||
int seed, count, find_non_zero;
|
||||
{
|
||||
size_t tmp;
|
||||
size_t tmp, len;
|
||||
mbstate_t ps;
|
||||
int point;
|
||||
wchar_t wc;
|
||||
@@ -99,7 +99,10 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
tmp = mbrtowc (&wc, string+point, strlen(string + point), &ps);
|
||||
len = strlen (string + point);
|
||||
if (len == 0)
|
||||
break;
|
||||
tmp = mbrtowc (&wc, string+point, len, &ps);
|
||||
if (MB_INVALIDCH ((size_t)tmp))
|
||||
{
|
||||
/* invalid bytes. assume a byte represents a character */
|
||||
|
||||
@@ -0,0 +1,372 @@
|
||||
/* mbutil.c -- readline multibyte character utility functions */
|
||||
|
||||
/* Copyright (C) 2001-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
|
||||
Readline is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Readline is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Readline. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define READLINE_LIBRARY
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include "posixjmp.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h> /* for _POSIX_VERSION */
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* System-specific feature definitions and include files. */
|
||||
#include "rldefs.h"
|
||||
#include "rlmbutil.h"
|
||||
|
||||
#if defined (TIOCSTAT_IN_SYS_IOCTL)
|
||||
# include <sys/ioctl.h>
|
||||
#endif /* TIOCSTAT_IN_SYS_IOCTL */
|
||||
|
||||
/* Some standard library routines. */
|
||||
#include "readline.h"
|
||||
|
||||
#include "rlprivate.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* Declared here so it can be shared between the readline and history
|
||||
libraries. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
int rl_byte_oriented = 0;
|
||||
#else
|
||||
int rl_byte_oriented = 1;
|
||||
#endif
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Multibyte Character Utility Functions */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
#if defined(HANDLE_MULTIBYTE)
|
||||
|
||||
static int
|
||||
_rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
|
||||
char *string;
|
||||
int seed, count, find_non_zero;
|
||||
{
|
||||
size_t tmp, len;
|
||||
mbstate_t ps;
|
||||
int point;
|
||||
wchar_t wc;
|
||||
|
||||
tmp = 0;
|
||||
|
||||
memset(&ps, 0, sizeof (mbstate_t));
|
||||
if (seed < 0)
|
||||
seed = 0;
|
||||
if (count <= 0)
|
||||
return seed;
|
||||
|
||||
point = seed + _rl_adjust_point (string, seed, &ps);
|
||||
/* if this is true, means that seed was not pointing to a byte indicating
|
||||
the beginning of a multibyte character. Correct the point and consume
|
||||
one char. */
|
||||
if (seed < point)
|
||||
count--;
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
tmp = mbrtowc (&wc, string+point, strlen(string + point), &ps);
|
||||
if (MB_INVALIDCH ((size_t)tmp))
|
||||
{
|
||||
/* invalid bytes. assume a byte represents a character */
|
||||
point++;
|
||||
count--;
|
||||
/* reset states. */
|
||||
memset(&ps, 0, sizeof(mbstate_t));
|
||||
}
|
||||
else if (MB_NULLWCH (tmp))
|
||||
break; /* found wide '\0' */
|
||||
else
|
||||
{
|
||||
/* valid bytes */
|
||||
point += tmp;
|
||||
if (find_non_zero)
|
||||
{
|
||||
if (wcwidth (wc) == 0)
|
||||
continue;
|
||||
else
|
||||
count--;
|
||||
}
|
||||
else
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
if (find_non_zero)
|
||||
{
|
||||
tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
|
||||
while (MB_NULLWCH (tmp) == 0 && MB_INVALIDCH (tmp) == 0 && wcwidth (wc) == 0)
|
||||
{
|
||||
point += tmp;
|
||||
tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
|
||||
}
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
static int
|
||||
_rl_find_prev_mbchar_internal (string, seed, find_non_zero)
|
||||
char *string;
|
||||
int seed, find_non_zero;
|
||||
{
|
||||
mbstate_t ps;
|
||||
int prev, non_zero_prev, point, length;
|
||||
size_t tmp;
|
||||
wchar_t wc;
|
||||
|
||||
memset(&ps, 0, sizeof(mbstate_t));
|
||||
length = strlen(string);
|
||||
|
||||
if (seed < 0)
|
||||
return 0;
|
||||
else if (length < seed)
|
||||
return length;
|
||||
|
||||
prev = non_zero_prev = point = 0;
|
||||
while (point < seed)
|
||||
{
|
||||
tmp = mbrtowc (&wc, string + point, length - point, &ps);
|
||||
if (MB_INVALIDCH ((size_t)tmp))
|
||||
{
|
||||
/* in this case, bytes are invalid or shorted to compose
|
||||
multibyte char, so assume that the first byte represents
|
||||
a single character anyway. */
|
||||
tmp = 1;
|
||||
/* clear the state of the byte sequence, because
|
||||
in this case effect of mbstate is undefined */
|
||||
memset(&ps, 0, sizeof (mbstate_t));
|
||||
|
||||
/* Since we're assuming that this byte represents a single
|
||||
non-zero-width character, don't forget about it. */
|
||||
prev = point;
|
||||
}
|
||||
else if (MB_NULLWCH (tmp))
|
||||
break; /* Found '\0' char. Can this happen? */
|
||||
else
|
||||
{
|
||||
if (find_non_zero)
|
||||
{
|
||||
if (wcwidth (wc) != 0)
|
||||
prev = point;
|
||||
}
|
||||
else
|
||||
prev = point;
|
||||
}
|
||||
|
||||
point += tmp;
|
||||
}
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* return the number of bytes parsed from the multibyte sequence starting
|
||||
at src, if a non-L'\0' wide character was recognized. It returns 0,
|
||||
if a L'\0' wide character was recognized. It returns (size_t)(-1),
|
||||
if an invalid multibyte sequence was encountered. It returns (size_t)(-2)
|
||||
if it couldn't parse a complete multibyte character. */
|
||||
int
|
||||
_rl_get_char_len (src, ps)
|
||||
char *src;
|
||||
mbstate_t *ps;
|
||||
{
|
||||
size_t tmp;
|
||||
|
||||
tmp = mbrlen((const char *)src, (size_t)strlen (src), ps);
|
||||
if (tmp == (size_t)(-2))
|
||||
{
|
||||
/* shorted to compose multibyte char */
|
||||
if (ps)
|
||||
memset (ps, 0, sizeof(mbstate_t));
|
||||
return -2;
|
||||
}
|
||||
else if (tmp == (size_t)(-1))
|
||||
{
|
||||
/* invalid to compose multibyte char */
|
||||
/* initialize the conversion state */
|
||||
if (ps)
|
||||
memset (ps, 0, sizeof(mbstate_t));
|
||||
return -1;
|
||||
}
|
||||
else if (tmp == (size_t)0)
|
||||
return 0;
|
||||
else
|
||||
return (int)tmp;
|
||||
}
|
||||
|
||||
/* compare the specified two characters. If the characters matched,
|
||||
return 1. Otherwise return 0. */
|
||||
int
|
||||
_rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2)
|
||||
char *buf1;
|
||||
int pos1;
|
||||
mbstate_t *ps1;
|
||||
char *buf2;
|
||||
int pos2;
|
||||
mbstate_t *ps2;
|
||||
{
|
||||
int i, w1, w2;
|
||||
|
||||
if ((w1 = _rl_get_char_len (&buf1[pos1], ps1)) <= 0 ||
|
||||
(w2 = _rl_get_char_len (&buf2[pos2], ps2)) <= 0 ||
|
||||
(w1 != w2) ||
|
||||
(buf1[pos1] != buf2[pos2]))
|
||||
return 0;
|
||||
|
||||
for (i = 1; i < w1; i++)
|
||||
if (buf1[pos1+i] != buf2[pos2+i])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* adjust pointed byte and find mbstate of the point of string.
|
||||
adjusted point will be point <= adjusted_point, and returns
|
||||
differences of the byte(adjusted_point - point).
|
||||
if point is invalied (point < 0 || more than string length),
|
||||
it returns -1 */
|
||||
int
|
||||
_rl_adjust_point(string, point, ps)
|
||||
char *string;
|
||||
int point;
|
||||
mbstate_t *ps;
|
||||
{
|
||||
size_t tmp = 0;
|
||||
int length;
|
||||
int pos = 0;
|
||||
|
||||
length = strlen(string);
|
||||
if (point < 0)
|
||||
return -1;
|
||||
if (length < point)
|
||||
return -1;
|
||||
|
||||
while (pos < point)
|
||||
{
|
||||
tmp = mbrlen (string + pos, length - pos, ps);
|
||||
if (MB_INVALIDCH ((size_t)tmp))
|
||||
{
|
||||
/* in this case, bytes are invalid or shorted to compose
|
||||
multibyte char, so assume that the first byte represents
|
||||
a single character anyway. */
|
||||
pos++;
|
||||
/* clear the state of the byte sequence, because
|
||||
in this case effect of mbstate is undefined */
|
||||
if (ps)
|
||||
memset (ps, 0, sizeof (mbstate_t));
|
||||
}
|
||||
else if (MB_NULLWCH (tmp))
|
||||
pos++;
|
||||
else
|
||||
pos += tmp;
|
||||
}
|
||||
|
||||
return (pos - point);
|
||||
}
|
||||
|
||||
int
|
||||
_rl_is_mbchar_matched (string, seed, end, mbchar, length)
|
||||
char *string;
|
||||
int seed, end;
|
||||
char *mbchar;
|
||||
int length;
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((end - seed) < length)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
if (string[seed + i] != mbchar[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
wchar_t
|
||||
_rl_char_value (buf, ind)
|
||||
char *buf;
|
||||
int ind;
|
||||
{
|
||||
size_t tmp;
|
||||
wchar_t wc;
|
||||
mbstate_t ps;
|
||||
int l;
|
||||
|
||||
if (MB_LEN_MAX == 1 || rl_byte_oriented)
|
||||
return ((wchar_t) buf[ind]);
|
||||
l = strlen (buf);
|
||||
if (ind >= l - 1)
|
||||
return ((wchar_t) buf[ind]);
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
tmp = mbrtowc (&wc, buf + ind, l - ind, &ps);
|
||||
if (MB_INVALIDCH (tmp) || MB_NULLWCH (tmp))
|
||||
return ((wchar_t) buf[ind]);
|
||||
return wc;
|
||||
}
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
/* Find next `count' characters started byte point of the specified seed.
|
||||
If flags is MB_FIND_NONZERO, we look for non-zero-width multibyte
|
||||
characters. */
|
||||
#undef _rl_find_next_mbchar
|
||||
int
|
||||
_rl_find_next_mbchar (string, seed, count, flags)
|
||||
char *string;
|
||||
int seed, count, flags;
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
return _rl_find_next_mbchar_internal (string, seed, count, flags);
|
||||
#else
|
||||
return (seed + count);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Find previous character started byte point of the specified seed.
|
||||
Returned point will be point <= seed. If flags is MB_FIND_NONZERO,
|
||||
we look for non-zero-width multibyte characters. */
|
||||
#undef _rl_find_prev_mbchar
|
||||
int
|
||||
_rl_find_prev_mbchar (string, seed, flags)
|
||||
char *string;
|
||||
int seed, flags;
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
return _rl_find_prev_mbchar_internal (string, seed, flags);
|
||||
#else
|
||||
return ((seed == 0) ? seed : seed - 1);
|
||||
#endif
|
||||
}
|
||||
+6
-1
@@ -1251,6 +1251,7 @@ rl_change_case (count, op)
|
||||
wchar_t wc, nwc;
|
||||
char mb[MB_LEN_MAX+1];
|
||||
int mlen;
|
||||
size_t m;
|
||||
mbstate_t mps;
|
||||
#endif
|
||||
|
||||
@@ -1303,7 +1304,11 @@ rl_change_case (count, op)
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
else
|
||||
{
|
||||
mbrtowc (&wc, rl_line_buffer + start, end - start, &mps);
|
||||
m = mbrtowc (&wc, rl_line_buffer + start, end - start, &mps);
|
||||
if (MB_INVALIDCH (m))
|
||||
wc = (wchar_t)rl_line_buffer[start];
|
||||
else if (MB_NULLWCH (m))
|
||||
wc = L'\0';
|
||||
nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc);
|
||||
if (nwc != wc) /* just skip unchanged characters */
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -769,6 +769,7 @@ _rl_vi_change_mbchar_case (count)
|
||||
wchar_t wc;
|
||||
char mb[MB_LEN_MAX+1];
|
||||
int mlen, p;
|
||||
size_t m;
|
||||
mbstate_t ps;
|
||||
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
@@ -776,7 +777,11 @@ _rl_vi_change_mbchar_case (count)
|
||||
count--;
|
||||
while (count-- && rl_point < rl_end)
|
||||
{
|
||||
mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
|
||||
m = mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
|
||||
if (MB_INVALIDCH (m))
|
||||
wc = (wchar_t)rl_line_buffer[rl_point];
|
||||
else if (MB_NULLWCH (m))
|
||||
wc = L'\0';
|
||||
if (iswupper (wc))
|
||||
wc = towlower (wc);
|
||||
else if (iswlower (wc))
|
||||
|
||||
@@ -131,9 +131,10 @@ static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
|
||||
void
|
||||
_rl_vi_initialize_line ()
|
||||
{
|
||||
register int i;
|
||||
register int i, n;
|
||||
|
||||
for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++)
|
||||
n = sizeof (vi_mark_chars) / sizeof (vi_mark_chars[0]);
|
||||
for (i = 0; i < n; i++)
|
||||
vi_mark_chars[i] = -1;
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_VICMDONCE);
|
||||
|
||||
+6
-2
@@ -526,6 +526,10 @@ casemod.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
|
||||
|
||||
fdprintf.o: ${BASHINCDIR}/stdc.h
|
||||
|
||||
input_avail.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
input_avail.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
input_avail.o: ${BASHINCDIR}/stdc.h
|
||||
input_avail.o: ${topdir}/xmalloc.h
|
||||
input_avail.o: ${topdir}/xmalloc.h ${BASHINCDIR}/posixselect.h
|
||||
|
||||
mktime.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
mktime.o: ${BASHINCDIR}/stdc.h
|
||||
|
||||
|
||||
+9
-3
@@ -91,7 +91,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
|
||||
strtoll.c strtoull.c strtoimax.c strtoumax.c memset.c strstr.c \
|
||||
mktime.c strftime.c mbschr.c zcatfd.c zmapfd.c winsize.c eaccess.c \
|
||||
wcsdup.c fpurge.c zgetline.c mbscmp.c uconvert.c ufuncs.c \
|
||||
casemod.c fdprintf.c input_avail.c
|
||||
casemod.c fdprintf.c input_avail.c mbscasecmp.c
|
||||
|
||||
# The header files for this library.
|
||||
HSOURCES =
|
||||
@@ -105,7 +105,7 @@ OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
|
||||
strtrans.o snprintf.o mailstat.o fmtulong.o \
|
||||
fmtullong.o fmtumax.o zcatfd.o zmapfd.o winsize.o wcsdup.o \
|
||||
fpurge.o zgetline.o mbscmp.o uconvert.o ufuncs.o casemod.o \
|
||||
fdprintf.o input_avail.o ${LIBOBJS}
|
||||
fdprintf.o input_avail.o mbscasecmp.o ${LIBOBJS}
|
||||
|
||||
SUPPORT = Makefile
|
||||
|
||||
@@ -153,6 +153,7 @@ input_avail.o: input_avail.c
|
||||
itos.o: itos.c
|
||||
mailstat.o: mailstat.c
|
||||
makepath.o: makepath.c
|
||||
mbscasecmp.o: mbscasecmp.c
|
||||
mbscmp.o: mbscmp.c
|
||||
memset.o: memset.c
|
||||
mktime.o: mktime.c
|
||||
@@ -221,6 +222,7 @@ input_avail.o: ${BUILD_DIR}/config.h
|
||||
itos.o: ${BUILD_DIR}/config.h
|
||||
mailstat.o: ${BUILD_DIR}/config.h
|
||||
makepath.o: ${BUILD_DIR}/config.h
|
||||
mbscasecmp.o: ${BUILD_DIR}/config.h
|
||||
mbscmp.o: ${BUILD_DIR}/config.h
|
||||
memset.o: ${BUILD_DIR}/config.h
|
||||
mktime.o: ${BUILD_DIR}/config.h
|
||||
@@ -507,6 +509,10 @@ zgetline.o: ${BASHINCDIR}/stdc.h
|
||||
zgetline.o: ${topdir}/xmalloc.h
|
||||
zgetline.o: ${topdir}/bashtypes.h
|
||||
|
||||
mbscasecmp.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
mbscasecmp.o: ${BASHINCDIR}/stdc.h
|
||||
mbscasecmp.o: ${topdir}/xmalloc.h
|
||||
|
||||
mbscmp.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
mbscmp.o: ${BASHINCDIR}/stdc.h
|
||||
mbscmp.o: ${topdir}/xmalloc.h
|
||||
@@ -522,4 +528,4 @@ fdprintf.o: ${BASHINCDIR}/stdc.h
|
||||
|
||||
input_avail.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
input_avail.o: ${BASHINCDIR}/stdc.h
|
||||
input_avail.o: ${topdir}/xmalloc.h
|
||||
input_avail.o: ${topdir}/xmalloc.h ${BASHINCDIR}/posixselect.h
|
||||
|
||||
+6
-1
@@ -107,6 +107,7 @@ sh_modcase (string, pat, flags)
|
||||
wchar_t nwc;
|
||||
char mb[MB_LEN_MAX+1];
|
||||
int mlen;
|
||||
size_t m;
|
||||
mbstate_t state;
|
||||
#endif
|
||||
|
||||
@@ -210,7 +211,11 @@ sh_modcase (string, pat, flags)
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
else
|
||||
{
|
||||
mbrtowc (&wc, string + start, end - start, &state);
|
||||
m = mbrtowc (&wc, string + start, end - start, &state);
|
||||
if (MB_INVALIDCH (m))
|
||||
wc = (wchar_t)string[start];
|
||||
else if (MB_NULLWCH (m))
|
||||
wc = L'\0';
|
||||
switch (nop)
|
||||
{
|
||||
default:
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
/* casemod.c -- functions to change case of strings */
|
||||
|
||||
/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
||||
#include <stdc.h>
|
||||
|
||||
#include <bashansi.h>
|
||||
#include <bashintl.h>
|
||||
#include <bashtypes.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <xmalloc.h>
|
||||
|
||||
#include <shmbutil.h>
|
||||
#include <chartypes.h>
|
||||
|
||||
#include <glob/strmatch.h>
|
||||
|
||||
#define _to_wupper(wc) (iswlower (wc) ? towupper (wc) : (wc))
|
||||
#define _to_wlower(wc) (iswupper (wc) ? towlower (wc) : (wc))
|
||||
|
||||
#if !defined (HANDLE_MULTIBYTE)
|
||||
# define cval(s, i) ((s)[(i)])
|
||||
# define iswalnum(c) (isalnum(c))
|
||||
# define TOGGLE(x) (ISUPPER (x) ? tolower (x) : (TOUPPER (x)))
|
||||
#else
|
||||
# define TOGGLE(x) (iswupper (x) ? towlower (x) : (_to_wupper(x)))
|
||||
#endif
|
||||
|
||||
/* These must agree with the defines in externs.h */
|
||||
#define CASE_NOOP 0x0000
|
||||
#define CASE_LOWER 0x0001
|
||||
#define CASE_UPPER 0x0002
|
||||
#define CASE_CAPITALIZE 0x0004
|
||||
#define CASE_UNCAP 0x0008
|
||||
#define CASE_TOGGLE 0x0010
|
||||
#define CASE_TOGGLEALL 0x0020
|
||||
#define CASE_UPFIRST 0x0040
|
||||
#define CASE_LOWFIRST 0x0080
|
||||
|
||||
#define CASE_USEWORDS 0x1000 /* modify behavior to act on words in passed string */
|
||||
|
||||
extern char *substring __P((char *, int, int));
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
static wchar_t
|
||||
cval (s, i)
|
||||
char *s;
|
||||
int i;
|
||||
{
|
||||
size_t tmp;
|
||||
wchar_t wc;
|
||||
int l;
|
||||
mbstate_t mps;
|
||||
|
||||
if (MB_CUR_MAX == 1)
|
||||
return ((wchar_t)s[i]);
|
||||
l = strlen (s);
|
||||
if (i >= (l - 1))
|
||||
return ((wchar_t)s[i]);
|
||||
memset (&mps, 0, sizeof (mbstate_t));
|
||||
tmp = mbrtowc (&wc, s + i, l - i, &mps);
|
||||
if (MB_INVALIDCH (tmp) || MB_NULLWCH (tmp))
|
||||
return ((wchar_t)s[i]);
|
||||
return wc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Modify the case of characters in STRING matching PAT based on the value of
|
||||
FLAGS. If PAT is null, modify the case of each character */
|
||||
char *
|
||||
sh_modcase (string, pat, flags)
|
||||
const char *string;
|
||||
char *pat;
|
||||
int flags;
|
||||
{
|
||||
int start, next, end;
|
||||
int inword, c, nc, nop, match, usewords;
|
||||
char *ret, *s;
|
||||
wchar_t wc;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
wchar_t nwc;
|
||||
char mb[MB_LEN_MAX+1];
|
||||
int mlen, m;
|
||||
mbstate_t state;
|
||||
#endif
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
memset (&state, 0, sizeof (mbstate_t));
|
||||
#endif
|
||||
|
||||
start = 0;
|
||||
end = strlen (string);
|
||||
|
||||
ret = (char *)xmalloc (end + 1);
|
||||
strcpy (ret, string);
|
||||
|
||||
/* See if we are supposed to split on alphanumerics and operate on each word */
|
||||
usewords = (flags & CASE_USEWORDS);
|
||||
flags &= ~CASE_USEWORDS;
|
||||
|
||||
inword = 0;
|
||||
while (start < end)
|
||||
{
|
||||
wc = cval (ret, start);
|
||||
|
||||
if (iswalnum (wc) == 0)
|
||||
{
|
||||
inword = 0;
|
||||
ADVANCE_CHAR (ret, end, start);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pat)
|
||||
{
|
||||
next = start;
|
||||
ADVANCE_CHAR (ret, end, next);
|
||||
s = substring (ret, start, next);
|
||||
match = strmatch (pat, s, FNM_EXTMATCH) != FNM_NOMATCH;
|
||||
free (s);
|
||||
if (match == 0)
|
||||
{
|
||||
start = next;
|
||||
inword = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX - for now, the toggling operators work on the individual
|
||||
words in the string, breaking on alphanumerics. Should I
|
||||
leave the capitalization operators to do that also? */
|
||||
if (flags == CASE_CAPITALIZE)
|
||||
{
|
||||
if (usewords)
|
||||
nop = inword ? CASE_LOWER : CASE_UPPER;
|
||||
else
|
||||
nop = (start > 0) ? CASE_LOWER : CASE_UPPER;
|
||||
inword = 1;
|
||||
}
|
||||
else if (flags == CASE_UNCAP)
|
||||
{
|
||||
if (usewords)
|
||||
nop = inword ? CASE_UPPER : CASE_LOWER;
|
||||
else
|
||||
nop = (start > 0) ? CASE_UPPER : CASE_LOWER;
|
||||
inword = 1;
|
||||
}
|
||||
else if (flags == CASE_UPFIRST)
|
||||
{
|
||||
if (usewords)
|
||||
nop = inword ? CASE_NOOP : CASE_UPPER;
|
||||
else
|
||||
nop = (start > 0) ? CASE_NOOP : CASE_UPPER;
|
||||
inword = 1;
|
||||
}
|
||||
else if (flags == CASE_LOWFIRST)
|
||||
{
|
||||
if (usewords)
|
||||
nop = inword ? CASE_NOOP : CASE_LOWER;
|
||||
else
|
||||
nop = (start > 0) ? CASE_NOOP : CASE_LOWER;
|
||||
inword = 1;
|
||||
}
|
||||
else if (flags == CASE_TOGGLE)
|
||||
{
|
||||
nop = inword ? CASE_NOOP : CASE_TOGGLE;
|
||||
inword = 1;
|
||||
}
|
||||
else
|
||||
nop = flags;
|
||||
|
||||
if (MB_CUR_MAX == 1 || isascii (wc))
|
||||
{
|
||||
switch (nop)
|
||||
{
|
||||
default:
|
||||
case CASE_NOOP: nc = wc; break;
|
||||
case CASE_UPPER: nc = TOUPPER (wc); break;
|
||||
case CASE_LOWER: nc = TOLOWER (wc); break;
|
||||
case CASE_TOGGLEALL:
|
||||
case CASE_TOGGLE: nc = TOGGLE (wc); break;
|
||||
}
|
||||
ret[start] = nc;
|
||||
}
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
else
|
||||
{
|
||||
m = mbrtowc (&wc, string + start, end - start, &state);
|
||||
if (MB_INVALIDCH (m))
|
||||
wc = (wchar_t)string[start];
|
||||
else if (MB_NULLWCH (m))
|
||||
wc = L'\0';
|
||||
switch (nop)
|
||||
{
|
||||
default:
|
||||
case CASE_NOOP: nwc = wc; break;
|
||||
case CASE_UPPER: nwc = TOUPPER (wc); break;
|
||||
case CASE_LOWER: nwc = TOLOWER (wc); break;
|
||||
case CASE_TOGGLEALL:
|
||||
case CASE_TOGGLE: nwc = TOGGLE (wc); break;
|
||||
}
|
||||
if (nwc != wc) /* just skip unchanged characters */
|
||||
{
|
||||
mlen = wcrtomb (mb, nwc, &state);
|
||||
if (mlen > 0)
|
||||
mb[mlen] = '\0';
|
||||
/* Assume the same width */
|
||||
strncpy (ret + start, mb, mlen);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This assumes that the upper and lower case versions are the same width. */
|
||||
ADVANCE_CHAR (ret, end, start);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user