Bash-4.2 distribution sources and documentation

This commit is contained in:
Chet Ramey 2011-11-22 19:11:26 -05:00
commit 495aee441b
341 changed files with 108751 additions and 36060 deletions

View file

@ -71,7 +71,7 @@ CSOURCES = $(srcdir)/glob.c $(srcdir)/strmatch.c $(srcdir)/smatch.c \
# The header files for this library.
HSOURCES = $(srcdir)/strmatch.h
OBJECTS = glob.o strmatch.o smatch.o xmbsrtowcs.o
OBJECTS = glob.o strmatch.o smatch.o xmbsrtowcs.o gmisc.o
# The texinfo files which document this library.
DOCSOURCE = doc/glob.texi
@ -119,6 +119,9 @@ realclean distclean maintainer-clean: clean
mostlyclean: clean
-( cd doc && $(MAKE) $(MFLAGS) $@ )
${BUILD_DIR}/pathnames.h: ${BUILD_DIR}/config.h ${BUILD_DIR}/Makefile Makefile
-( cd ${BUILD_DIR} && ${MAKE} ${MFLAGS} pathnames.h )
######################################################################
# #
# Dependencies for the object files which make up this library. #
@ -137,18 +140,24 @@ strmatch.o: $(BUILD_DIR)/config.h
strmatch.o: $(BASHINCDIR)/stdc.h
glob.o: $(BUILD_DIR)/config.h
glob.o: $(topdir)/shell.h $(BUILD_DIR)/pathnames.h
glob.o: $(topdir)/bashtypes.h $(BASHINCDIR)/ansi_stdlib.h $(topdir)/bashansi.h
glob.o: $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/memalloc.h
glob.o: strmatch.h glob.h
glob.o: $(BASHINCDIR)/shmbutil.h
glob.o: $(topdir)/xmalloc.h
gmisc.o: $(BUILD_DIR)/config.h
gmisc.o: $(topdir)/bashtypes.h $(BASHINCDIR)/ansi_stdlib.h $(topdir)/bashansi.h
gmisc.o: $(BASHINCDIR)/shmbutil.h
xmbsrtowcs.o: ${BUILD_DIR}/config.h
xmbsrtowcs.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
xmbsrtowcs.o: ${BASHINCDIR}/shmbutil.h
# Rules for deficient makes, like SunOS and Solaris
glob.o: glob.c
gmisc.o: gmisc.c
strmatch.o: strmatch.c
smatch.o: smatch.c
xmbsrtowcs.o: xmbsrtowcs.c

314
lib/glob/gmisc.c Normal file
View file

@ -0,0 +1,314 @@
/* gmisc.c -- miscellaneous pattern matching utility functions for Bash.
Copyright (C) 2010 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/>.
*/
#include <config.h>
#include "bashtypes.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "bashansi.h"
#include "shmbutil.h"
#include "stdc.h"
#ifndef LPAREN
# define LPAREN '('
#endif
#ifndef RPAREN
# define RPAREN ')'
#endif
#if defined (HANDLE_MULTIBYTE)
#define WLPAREN L'('
#define WRPAREN L')'
/* Return 1 of the first character of WSTRING could match the first
character of pattern WPAT. Wide character version. */
int
match_pattern_wchar (wpat, wstring)
wchar_t *wpat, *wstring;
{
wchar_t wc;
if (*wstring == 0)
return (0);
switch (wc = *wpat++)
{
default:
return (*wstring == wc);
case L'\\':
return (*wstring == *wpat);
case L'?':
return (*wpat == WLPAREN ? 1 : (*wstring != L'\0'));
case L'*':
return (1);
case L'+':
case L'!':
case L'@':
return (*wpat == WLPAREN ? 1 : (*wstring == wc));
case L'[':
return (*wstring != L'\0');
}
}
int
wmatchlen (wpat, wmax)
wchar_t *wpat;
size_t wmax;
{
wchar_t wc, *wbrack;
int matlen, t, in_cclass, in_collsym, in_equiv;
if (*wpat == 0)
return (0);
matlen = in_cclass = in_collsym = in_equiv = 0;
while (wc = *wpat++)
{
switch (wc)
{
default:
matlen++;
break;
case L'\\':
if (*wpat == 0)
return ++matlen;
else
{
matlen++;
wpat++;
}
break;
case L'?':
if (*wpat == WLPAREN)
return (matlen = -1); /* XXX for now */
else
matlen++;
break;
case L'*':
return (matlen = -1);
case L'+':
case L'!':
case L'@':
if (*wpat == WLPAREN)
return (matlen = -1); /* XXX for now */
else
matlen++;
break;
case L'[':
/* scan for ending `]', skipping over embedded [:...:] */
wbrack = wpat;
wc = *wpat++;
do
{
if (wc == 0)
{
matlen += wpat - wbrack - 1; /* incremented below */
break;
}
else if (wc == L'\\')
{
wc = *wpat++;
if (*wpat == 0)
break;
}
else if (wc == L'[' && *wpat == L':') /* character class */
{
wpat++;
in_cclass = 1;
}
else if (in_cclass && wc == L':' && *wpat == L']')
{
wpat++;
in_cclass = 0;
}
else if (wc == L'[' && *wpat == L'.') /* collating symbol */
{
wpat++;
if (*wpat == L']') /* right bracket can appear as collating symbol */
wpat++;
in_collsym = 1;
}
else if (in_collsym && wc == L'.' && *wpat == L']')
{
wpat++;
in_collsym = 0;
}
else if (wc == L'[' && *wpat == L'=') /* equivalence class */
{
wpat++;
if (*wpat == L']') /* right bracket can appear as equivalence class */
wpat++;
in_equiv = 1;
}
else if (in_equiv && wc == L'=' && *wpat == L']')
{
wpat++;
in_equiv = 0;
}
}
while ((wc = *wpat++) != L']');
matlen++; /* bracket expression can only match one char */
break;
}
}
return matlen;
}
#endif
/* Return 1 of the first character of STRING could match the first
character of pattern PAT. Used to avoid n2 calls to strmatch(). */
int
match_pattern_char (pat, string)
char *pat, *string;
{
char c;
if (*string == 0)
return (0);
switch (c = *pat++)
{
default:
return (*string == c);
case '\\':
return (*string == *pat);
case '?':
return (*pat == LPAREN ? 1 : (*string != '\0'));
case '*':
return (1);
case '+':
case '!':
case '@':
return (*pat == LPAREN ? 1 : (*string == c));
case '[':
return (*string != '\0');
}
}
int
umatchlen (pat, max)
char *pat;
size_t max;
{
char c, *brack;
int matlen, t, in_cclass, in_collsym, in_equiv;
if (*pat == 0)
return (0);
matlen = in_cclass = in_collsym = in_equiv = 0;
while (c = *pat++)
{
switch (c)
{
default:
matlen++;
break;
case '\\':
if (*pat == 0)
return ++matlen;
else
{
matlen++;
pat++;
}
break;
case '?':
if (*pat == LPAREN)
return (matlen = -1); /* XXX for now */
else
matlen++;
break;
case '*':
return (matlen = -1);
case '+':
case '!':
case '@':
if (*pat == LPAREN)
return (matlen = -1); /* XXX for now */
else
matlen++;
break;
case '[':
/* scan for ending `]', skipping over embedded [:...:] */
brack = pat;
c = *pat++;
do
{
if (c == 0)
{
matlen += pat - brack - 1; /* incremented below */
break;
}
else if (c == '\\')
{
c = *pat++;
if (*pat == 0)
break;
}
else if (c == '[' && *pat == ':') /* character class */
{
pat++;
in_cclass = 1;
}
else if (in_cclass && c == ':' && *pat == ']')
{
pat++;
in_cclass = 0;
}
else if (c == '[' && *pat == '.') /* collating symbol */
{
pat++;
if (*pat == ']') /* right bracket can appear as collating symbol */
pat++;
in_collsym = 1;
}
else if (in_collsym && c == '.' && *pat == ']')
{
pat++;
in_collsym = 0;
}
else if (c == '[' && *pat == '=') /* equivalence class */
{
pat++;
if (*pat == ']') /* right bracket can appear as equivalence class */
pat++;
in_equiv = 1;
}
else if (in_equiv && c == '=' && *pat == ']')
{
pat++;
in_equiv = 0;
}
}
while ((c = *pat++) != ']');
matlen++; /* bracket expression can only match one char */
break;
}
}
return matlen;
}

View file

@ -1,7 +1,7 @@
/* strmatch.c -- ksh-like extended pattern matching for the shell and filename
globbing. */
/* Copyright (C) 1991-2005 Free Software Foundation, Inc.
/* Copyright (C) 1991-2011 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -241,6 +241,8 @@ is_cclass (c, name)
# define STREQ(s1, s2) ((wcscmp (s1, s2) == 0))
# define STREQN(a, b, n) ((a)[0] == (b)[0] && wcsncmp(a, b, n) == 0)
extern char *mbsmbchar __P((const char *));
static int
rangecmp_wc (c1, c2)
wint_t c1, c2;
@ -314,7 +316,7 @@ is_wcclass (wc, name)
memset (&state, '\0', sizeof (mbstate_t));
mbs = (char *) malloc (wcslen(name) * MB_CUR_MAX + 1);
mbslength = wcsrtombs(mbs, (const wchar_t **)&name, (wcslen(name) * MB_CUR_MAX + 1), &state);
mbslength = wcsrtombs (mbs, (const wchar_t **)&name, (wcslen(name) * MB_CUR_MAX + 1), &state);
if (mbslength == (size_t)-1 || mbslength == (size_t)-2)
{
@ -365,6 +367,16 @@ xstrmatch (pattern, string, flags)
int ret;
size_t n;
wchar_t *wpattern, *wstring;
size_t plen, slen, mplen, mslen;
#if 0
plen = strlen (pattern);
mplen = mbstrlen (pattern);
if (plen == mplen && strlen (string) == mbstrlen (string))
#else
if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0)
#endif
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
if (MB_CUR_MAX == 1)
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));

View file

@ -1,6 +1,6 @@
/* xmbsrtowcs.c -- replacement function for mbsrtowcs */
/* Copyright (C) 2002-2004 Free Software Foundation, Inc.
/* Copyright (C) 2002-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -18,6 +18,12 @@
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
/* Ask for GNU extensions to get extern declaration for mbsnrtowcs if
available via glibc. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
#include <config.h>
#include <bashansi.h>
@ -32,6 +38,11 @@
#ifndef FREE
# define FREE(x) do { if (x) free (x); } while (0)
#endif
#if ! HAVE_STRCHRNUL
extern char *strchrnul __P((const char *, int));
#endif
/* On some locales (ex. ja_JP.sjis), mbsrtowc doesn't convert 0x5c to U<0x5c>.
So, this function is made for converting 0x5c to U<0x5c>. */
@ -120,6 +131,94 @@ xmbsrtowcs (dest, src, len, pstate)
return (wclength);
}
#if HAVE_MBSNRTOWCS
/* Convert a multibyte string to a wide character string. Memory for the
new wide character string is obtained with malloc.
Fast multiple-character version of xdupmbstowcs used when the indices are
not required and mbsnrtowcs is available. */
static size_t
xdupmbstowcs2 (destp, src)
wchar_t **destp; /* Store the pointer to the wide character string */
const char *src; /* Multibyte character string */
{
const char *p; /* Conversion start position of src */
wchar_t *wsbuf; /* Buffer for wide characters. */
size_t wsbuf_size; /* Size of WSBUF */
size_t wcnum; /* Number of wide characters in WSBUF */
mbstate_t state; /* Conversion State */
size_t wcslength; /* Number of wide characters produced by the conversion. */
const char *end_or_backslash;
size_t nms; /* Number of multibyte characters to convert at one time. */
mbstate_t tmp_state;
const char *tmp_p;
memset (&state, '\0', sizeof(mbstate_t));
wsbuf_size = 0;
wsbuf = NULL;
p = src;
wcnum = 0;
do
{
end_or_backslash = strchrnul(p, '\\');
nms = (end_or_backslash - p);
if (*end_or_backslash == '\0')
nms++;
/* Compute the number of produced wide-characters. */
tmp_p = p;
tmp_state = state;
wcslength = mbsnrtowcs(NULL, &tmp_p, nms, 0, &tmp_state);
/* Conversion failed. */
if (wcslength == (size_t)-1)
{
free (wsbuf);
*destp = NULL;
return (size_t)-1;
}
/* Resize the buffer if it is not large enough. */
if (wsbuf_size < wcnum+wcslength+1) /* 1 for the L'\0' or the potential L'\\' */
{
wchar_t *wstmp;
wsbuf_size = wcnum+wcslength+1; /* 1 for the L'\0' or the potential L'\\' */
wstmp = (wchar_t *) realloc (wsbuf, wsbuf_size * sizeof (wchar_t));
if (wstmp == NULL)
{
free (wsbuf);
*destp = NULL;
return (size_t)-1;
}
wsbuf = wstmp;
}
/* Perform the conversion. This is assumed to return 'wcslength'.
* It may set 'p' to NULL. */
mbsnrtowcs(wsbuf+wcnum, &p, nms, wsbuf_size-wcnum, &state);
wcnum += wcslength;
if (mbsinit (&state) && (p != NULL) && (*p == '\\'))
{
wsbuf[wcnum++] = L'\\';
p++;
}
}
while (p != NULL);
*destp = wsbuf;
/* Return the length of the wide character string, not including `\0'. */
return wcnum;
}
#endif /* HAVE_MBSNRTOWCS */
/* Convert a multibyte string to a wide character string. Memory for the
new wide character string is obtained with malloc.
@ -155,6 +254,11 @@ xdupmbstowcs (destp, indicesp, src)
return (size_t)-1;
}
#if HAVE_MBSNRTOWCS
if (indicesp == NULL)
return (xdupmbstowcs2 (destp, src));
#endif
memset (&state, '\0', sizeof(mbstate_t));
wsbuf_size = WSBUF_INC;

View file

@ -112,6 +112,7 @@ alloca.o: $(BUILD_DIR)/config.h
malloc.o: $(BUILD_DIR)/config.h $(topdir)/bashtypes.h getpagesize.h
xmalloc.o: $(BUILD_DIR)/config.h $(BASHINCDIR)/ansi_stdlib.h
trace.o: ${BUILD_DIR}/config.h
stats.o: ${BUILD_DIR}/config.h
table.o: ${BUILD_DIR}/config.h
watch.o: ${BUILD_DIR}/config.h

View file

@ -83,7 +83,7 @@ CSOURCES = $(srcdir)/readline.c $(srcdir)/funmap.c $(srcdir)/keymaps.c \
$(srcdir)/histfile.c $(srcdir)/nls.c $(srcdir)/search.c \
$(srcdir)/shell.c $(srcdir)/tilde.c $(srcdir)/savestring.c \
$(srcdir)/text.c $(srcdir)/misc.c $(srcdir)/compat.c \
$(srcdir)/mbutil.c
$(srcdir)/mbutil.c $(srcdir)/xfree.c
# The header files for this library.
HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h histlib.h \
@ -97,7 +97,7 @@ TILDEOBJ = tilde.o
OBJECTS = readline.o vi_mode.o funmap.o keymaps.o parens.o search.o \
rltty.o complete.o bind.o isearch.o display.o signals.o \
util.o kill.o undo.o macro.o input.o callback.o terminal.o \
text.o nls.o misc.o $(HISTOBJ) $(TILDEOBJ) xmalloc.o compat.o
text.o nls.o misc.o $(HISTOBJ) $(TILDEOBJ) xmalloc.o xfree.o compat.o
# The texinfo files which document this library.
DOCSOURCE = doc/rlman.texinfo doc/rltech.texinfo doc/rluser.texinfo
@ -123,9 +123,9 @@ libreadline.a: $(OBJECTS)
$(AR) $(ARFLAGS) $@ $(OBJECTS)
-test -n "$(RANLIB)" && $(RANLIB) $@
libhistory.a: $(HISTOBJ) xmalloc.o
libhistory.a: $(HISTOBJ) xmalloc.o xfree.o
$(RM) $@
$(AR) $(ARFLAGS) $@ $(HISTOBJ) xmalloc.o
$(AR) $(ARFLAGS) $@ $(HISTOBJ) xmalloc.o xfree.o
-test -n "$(RANLIB)" && $(RANLIB) $@
documentation: force
@ -262,6 +262,7 @@ vi_mode.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
vi_mode.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
vi_mode.o: history.h ansi_stdlib.h rlstdc.h
xmalloc.o: ${BUILD_DIR}/config.h ansi_stdlib.h
xfree.o: ${BUILD_DIR}/config.h ansi_stdlib.h
bind.o: rlshell.h
histfile.o: rlshell.h
@ -317,6 +318,7 @@ tilde.o: xmalloc.h
undo.o: xmalloc.h
util.o: xmalloc.h
vi_mode.o: xmalloc.h
xfree.o: xmalloc.h
xmalloc.o: xmalloc.h
complete.o: rlmbutil.h
@ -359,6 +361,7 @@ tilde.o: tilde.c
undo.o: undo.c
util.o: util.c
vi_mode.o: vi_mode.c
xfree.o: xfree.c
xmalloc.o: xmalloc.c
histexpand.o: histexpand.c

View file

@ -1,6 +1,6 @@
/* bind.c -- key binding and startup file support for the readline library. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2010 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.
@ -1424,6 +1424,7 @@ static const struct {
{ "blink-matching-paren", &rl_blink_matching_paren, V_SPECIAL },
{ "byte-oriented", &rl_byte_oriented, 0 },
{ "completion-ignore-case", &_rl_completion_case_fold, 0 },
{ "completion-map-case", &_rl_completion_case_map, 0 },
{ "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 },
{ "disable-completion", &rl_inhibit_completion, 0 },
{ "echo-control-characters", &_rl_echo_control_chars, 0 },
@ -1437,6 +1438,7 @@ static const struct {
{ "mark-modified-lines", &_rl_mark_modified_lines, 0 },
{ "mark-symlinked-directories", &_rl_complete_mark_symlink_dirs, 0 },
{ "match-hidden-files", &_rl_match_hidden_files, 0 },
{ "menu-complete-display-prefix", &_rl_menu_complete_prefix_first, 0 },
{ "meta-flag", &_rl_meta_flag, 0 },
{ "output-meta", &_rl_output_meta_chars, 0 },
{ "page-completions", &_rl_page_completions, 0 },
@ -1449,7 +1451,7 @@ static const struct {
#if defined (VISIBLE_STATS)
{ "visible-stats", &rl_visible_stats, 0 },
#endif /* VISIBLE_STATS */
{ (char *)NULL, (int *)NULL }
{ (char *)NULL, (int *)NULL, 0 }
};
static int
@ -1504,6 +1506,7 @@ static int sv_bell_style PARAMS((const char *));
static int sv_combegin PARAMS((const char *));
static int sv_dispprefix PARAMS((const char *));
static int sv_compquery PARAMS((const char *));
static int sv_compwidth PARAMS((const char *));
static int sv_editmode PARAMS((const char *));
static int sv_histsize PARAMS((const char *));
static int sv_isrchterm PARAMS((const char *));
@ -1516,13 +1519,14 @@ static const struct {
} string_varlist[] = {
{ "bell-style", V_STRING, sv_bell_style },
{ "comment-begin", V_STRING, sv_combegin },
{ "completion-display-width", V_INT, sv_compwidth },
{ "completion-prefix-display-length", V_INT, sv_dispprefix },
{ "completion-query-items", V_INT, sv_compquery },
{ "editing-mode", V_STRING, sv_editmode },
{ "history-size", V_INT, sv_histsize },
{ "isearch-terminators", V_STRING, sv_isrchterm },
{ "keymap", V_STRING, sv_keymap },
{ (char *)NULL, 0 }
{ (char *)NULL, 0, (_rl_sv_func_t *)0 }
};
static int
@ -1662,6 +1666,19 @@ sv_compquery (value)
return 0;
}
static int
sv_compwidth (value)
const char *value;
{
int nval = -1;
if (value && *value)
nval = atoi (value);
_rl_completion_columns = nval;
return 0;
}
static int
sv_histsize (value)
const char *value;
@ -2268,6 +2285,11 @@ _rl_get_string_variable_value (name)
}
else if (_rl_stricmp (name, "comment-begin") == 0)
return (_rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
else if (_rl_stricmp (name, "completion-display-width") == 0)
{
sprintf (numbuf, "%d", _rl_completion_columns);
return (numbuf);
}
else if (_rl_stricmp (name, "completion-prefix-display-length") == 0)
{
sprintf (numbuf, "%d", _rl_completion_prefix_display_length);

View file

@ -142,6 +142,15 @@ rl_callback_read_char ()
eof = _rl_nsearch_callback (_rl_nscxt);
return;
}
#if defined (VI_MODE)
else if (RL_ISSTATE (RL_STATE_VIMOTION))
{
eof = _rl_vi_domove_callback (_rl_vimvcxt);
/* Should handle everything, including cleanup, numeric arguments,
and turning off RL_STATE_VIMOTION */
return;
}
#endif
else if (RL_ISSTATE (RL_STATE_NUMERICARG))
{
eof = _rl_arg_callback (_rl_argcxt);

View file

@ -1,6 +1,6 @@
/* complete.c -- filename completion for readline. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2011 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.
@ -119,9 +119,11 @@ static char **remove_duplicate_matches PARAMS((char **));
static void insert_match PARAMS((char *, int, int, char *));
static int append_to_match PARAMS((char *, int, int, int));
static void insert_all_matches PARAMS((char **, int, char *));
static int complete_fncmp PARAMS((const char *, int, const char *, int));
static void display_matches PARAMS((char **));
static int compute_lcd_of_matches PARAMS((char **, int, const char *));
static int postprocess_matches PARAMS((char ***, int));
static int complete_get_screenwidth PARAMS((void));
static char *make_quoted_replacement PARAMS((char *, int, char *));
@ -157,10 +159,14 @@ int _rl_print_completions_horizontally;
#if defined (__MSDOS__) && !defined (__DJGPP__)
int _rl_completion_case_fold = 1;
#else
int _rl_completion_case_fold;
int _rl_completion_case_fold = 0;
#endif
/* If non-zero, don't match hidden files (filenames beginning with a `.' on
/* Non-zero means that `-' and `_' are equivalent when comparing filenames
for completion. */
int _rl_completion_case_map = 0;
/* If zero, don't match hidden files (filenames beginning with a `.' on
Unix) when doing filename completion. */
int _rl_match_hidden_files = 1;
@ -170,6 +176,10 @@ int _rl_match_hidden_files = 1;
display prefix replaced with an ellipsis. */
int _rl_completion_prefix_display_length = 0;
/* The readline-private number of screen columns to use when displaying
matches. If < 0 or > _rl_screenwidth, it is ignored. */
int _rl_completion_columns = -1;
/* Global variables available to applications using readline. */
#if defined (VISIBLE_STATS)
@ -185,6 +195,10 @@ int rl_visible_stats = 0;
after the `e' in `Makefile' won't result in `Makefilefile'. */
int _rl_skip_completed_text = 0;
/* If non-zero, menu completion displays the common prefix first in the
cycle of possible completions instead of the last. */
int _rl_menu_complete_prefix_first = 0;
/* If non-zero, then this is the address of a function to call when
completing on a directory name. The function is called with
the address of a string (the current directory name) as an arg. */
@ -467,6 +481,14 @@ get_y_or_n (for_pager)
{
int c;
/* For now, disable pager in callback mode, until we later convert to state
driven functions. Have to wait until next major version to add new
state definition, since it will change value of RL_STATE_DONE. */
#if defined (READLINE_CALLBACKS)
if (RL_ISSTATE (RL_STATE_CALLBACK))
return 1;
#endif
for (;;)
{
RL_SETSTATE(RL_STATE_MOREINPUT);
@ -829,7 +851,7 @@ print_filename (to_print, full_pathname, prefix_bytes)
if (path_isdir (new_full_pathname))
extension_char = '/';
free (new_full_pathname);
xfree (new_full_pathname);
to_print[-1] = c;
}
else
@ -844,7 +866,7 @@ print_filename (to_print, full_pathname, prefix_bytes)
extension_char = '/';
}
free (s);
xfree (s);
if (extension_char)
{
putc (extension_char, rl_outstream);
@ -1081,7 +1103,7 @@ remove_duplicate_matches (matches)
{
if (strcmp (matches[i], matches[i + 1]) == 0)
{
free (matches[i]);
xfree (matches[i]);
matches[i] = (char *)&dead_slot;
}
else
@ -1099,7 +1121,7 @@ remove_duplicate_matches (matches)
temp_array[j] = (char *)NULL;
if (matches[0] != (char *)&dead_slot)
free (matches[0]);
xfree (matches[0]);
/* Place the lowest common denominator back in [0]. */
temp_array[0] = lowest_common;
@ -1109,7 +1131,7 @@ remove_duplicate_matches (matches)
insert. */
if (j == 2 && strcmp (temp_array[0], temp_array[1]) == 0)
{
free (temp_array[1]);
xfree (temp_array[1]);
temp_array[1] = (char *)NULL;
}
return (temp_array);
@ -1288,7 +1310,7 @@ postprocess_matches (matchesp, matching_filenames)
if (rl_ignore_completion_duplicates)
{
temp_matches = remove_duplicate_matches (matches);
free (matches);
xfree (matches);
matches = temp_matches;
}
@ -1325,6 +1347,23 @@ postprocess_matches (matchesp, matching_filenames)
return (1);
}
static int
complete_get_screenwidth ()
{
int cols;
char *envcols;
cols = _rl_completion_columns;
if (cols >= 0 && cols <= _rl_screenwidth)
return cols;
envcols = getenv ("COLUMNS");
if (envcols && *envcols)
cols = atoi (envcols);
if (cols >= 0 && cols <= _rl_screenwidth)
return cols;
return _rl_screenwidth;
}
/* A convenience function for displaying a list of strings in
columnar format on readline's output stream. MATCHES is the list
of strings, in argv format, LEN is the number of strings in MATCHES,
@ -1334,7 +1373,7 @@ rl_display_match_list (matches, len, max)
char **matches;
int len, max;
{
int count, limit, printed_len, lines;
int count, limit, printed_len, lines, cols;
int i, j, k, l, common_length, sind;
char *temp, *t;
@ -1355,12 +1394,17 @@ rl_display_match_list (matches, len, max)
}
/* How many items of MAX length can we fit in the screen window? */
cols = complete_get_screenwidth ();
max += 2;
limit = _rl_screenwidth / max;
if (limit != 1 && (limit * max == _rl_screenwidth))
limit = cols / max;
if (limit != 1 && (limit * max == cols))
limit--;
/* Avoid a possible floating exception. If max > _rl_screenwidth,
/* If cols == 0, limit will end up -1 */
if (cols < _rl_screenwidth && limit < 0)
limit = 1;
/* Avoid a possible floating exception. If max > cols,
limit will be 0 and a divide-by-zero fault will result. */
if (limit == 0)
limit = 1;
@ -1608,7 +1652,7 @@ insert_match (match, start, mtype, qc)
else
_rl_replace_text (replacement, start, end);
if (replacement != match)
free (replacement);
xfree (replacement);
}
}
@ -1675,7 +1719,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
if (rl_point == rl_end && temp_string_index)
rl_insert_text (temp_string);
}
free (filename);
xfree (filename);
}
else
{
@ -1711,7 +1755,7 @@ insert_all_matches (matches, point, qc)
rl_insert_text (rp);
rl_insert_text (" ");
if (rp != matches[i])
free (rp);
xfree (rp);
}
}
else
@ -1720,7 +1764,7 @@ insert_all_matches (matches, point, qc)
rl_insert_text (rp);
rl_insert_text (" ");
if (rp != matches[0])
free (rp);
xfree (rp);
}
rl_end_undo_group ();
}
@ -1735,8 +1779,8 @@ _rl_free_match_list (matches)
return;
for (i = 0; matches[i]; i++)
free (matches[i]);
free (matches);
xfree (matches[i]);
xfree (matches);
}
/* Complete the word at or before point.
@ -1757,6 +1801,9 @@ rl_complete_internal (what_to_do)
int start, end, delimiter, found_quote, i, nontrivial_lcd;
char *text, *saved_line_buffer;
char quote_char;
#if 1
int tlen, mlen;
#endif
RL_SETSTATE(RL_STATE_COMPLETING);
@ -1784,7 +1831,11 @@ rl_complete_internal (what_to_do)
/* nontrivial_lcd is set if the common prefix adds something to the word
being completed. */
nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
free (text);
#if 1
if (what_to_do == '!' || what_to_do == '@')
tlen = strlen (text);
#endif
xfree (text);
if (matches == 0)
{
@ -1817,8 +1868,25 @@ rl_complete_internal (what_to_do)
case '!':
case '@':
/* Insert the first match with proper quoting. */
#if 0
if (*matches[0])
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
#else
if (what_to_do == TAB)
{
if (*matches[0])
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
}
else if (*matches[0] && matches[1] == 0)
/* should we perform the check only if there are multiple matches? */
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
else if (*matches[0]) /* what_to_do != TAB && multiple matches */
{
mlen = *matches[0] ? strlen (matches[0]) : 0;
if (mlen >= tlen)
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
}
#endif
/* If there are more matches, ring the bell to indicate.
If we are in vi mode, Posix.2 says to not ring the bell.
@ -1872,7 +1940,7 @@ rl_complete_internal (what_to_do)
if (saved_line_buffer)
{
completion_changed_buffer = strcmp (rl_line_buffer, saved_line_buffer) != 0;
free (saved_line_buffer);
xfree (saved_line_buffer);
}
RL_UNSETSTATE(RL_STATE_COMPLETING);
@ -1939,7 +2007,7 @@ rl_completion_matches (text, entry_function)
compute_lcd_of_matches (match_list, matches, text);
else /* There were no matches. */
{
free (match_list);
xfree (match_list);
match_list = (char **)NULL;
}
return (match_list);
@ -2005,6 +2073,62 @@ rl_username_completion_function (text, state)
#endif /* !__WIN32__ && !__OPENNT */
}
/* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME
(FILENAME_LEN). If _rl_completion_case_fold is set, compare without
regard to the alphabetic case of characters. CONVFN is the possibly-
converted directory entry; FILENAME is what the user typed. */
static int
complete_fncmp (convfn, convlen, filename, filename_len)
const char *convfn;
int convlen;
const char *filename;
int filename_len;
{
register char *s1, *s2;
int d, len;
/* Otherwise, if these match up to the length of filename, then
it is a match. */
if (_rl_completion_case_fold && _rl_completion_case_map)
{
/* Case-insensitive comparison treating _ and - as equivalent */
if (filename_len == 0)
return 1;
if (convlen < filename_len)
return 0;
s1 = (char *)convfn;
s2 = (char *)filename;
len = filename_len;
do
{
d = _rl_to_lower (*s1) - _rl_to_lower (*s2);
/* *s1 == [-_] && *s2 == [-_] */
if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
d = 0;
if (d != 0)
return 0;
s1++; s2++; /* already checked convlen >= filename_len */
}
while (--len != 0);
return 1;
}
else if (_rl_completion_case_fold)
{
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
(convlen >= filename_len) &&
(_rl_strnicmp (filename, convfn, filename_len) == 0))
return 1;
}
else
{
if ((convfn[0] == filename[0]) &&
(convlen >= filename_len) &&
(strncmp (filename, convfn, filename_len) == 0))
return 1;
}
return 0;
}
/* Okay, now we write the entry_function for filename completion. In the
general case. Note that completion in the shell is a little different
because of all the pathnames that must be followed when looking up the
@ -2071,32 +2195,41 @@ rl_filename_completion_function (text, state)
/* We aren't done yet. We also support the "~user" syntax. */
/* Save the version of the directory that the user typed. */
users_dirname = savestring (dirname);
/* Save the version of the directory that the user typed, dequoting
it if necessary. */
if (rl_completion_found_quote && rl_filename_dequoting_function)
users_dirname = (*rl_filename_dequoting_function) (dirname, rl_completion_quote_character);
else
users_dirname = savestring (dirname);
if (*dirname == '~')
{
temp = tilde_expand (dirname);
free (dirname);
xfree (dirname);
dirname = temp;
}
/* We have saved the possibly-dequoted version of the directory name
the user typed. Now transform the directory name we're going to
pass to opendir(2). The directory rewrite hook modifies only the
directory name; the directory completion hook modifies both the
directory name passed to opendir(2) and the version the user
typed. Both the directory completion and rewrite hooks should perform
any necessary dequoting. The hook functions return 1 if they modify
the directory name argument. If either hook returns 0, it should
not modify the directory name pointer passed as an argument. */
if (rl_directory_rewrite_hook)
(*rl_directory_rewrite_hook) (&dirname);
/* The directory completion hook should perform any necessary
dequoting. */
if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname))
else if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname))
{
free (users_dirname);
xfree (users_dirname);
users_dirname = savestring (dirname);
}
else if (rl_completion_found_quote && rl_filename_dequoting_function)
{
/* delete single and double quotes */
temp = (*rl_filename_dequoting_function) (users_dirname, rl_completion_quote_character);
free (users_dirname);
users_dirname = temp;
xfree (dirname);
dirname = savestring (users_dirname);
}
directory = opendir (dirname);
@ -2105,7 +2238,7 @@ rl_filename_completion_function (text, state)
{
/* delete single and double quotes */
temp = (*rl_filename_dequoting_function) (filename, rl_completion_quote_character);
free (filename);
xfree (filename);
filename = temp;
}
filename_len = strlen (filename);
@ -2147,22 +2280,8 @@ rl_filename_completion_function (text, state)
}
else
{
/* Otherwise, if these match up to the length of filename, then
it is a match. */
if (_rl_completion_case_fold)
{
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
(convlen >= filename_len) &&
(_rl_strnicmp (filename, convfn, filename_len) == 0))
break;
}
else
{
if ((convfn[0] == filename[0]) &&
(convlen >= filename_len) &&
(strncmp (filename, convfn, filename_len) == 0))
break;
}
if (complete_fncmp (convfn, convlen, filename, filename_len))
break;
}
}
@ -2175,17 +2294,17 @@ rl_filename_completion_function (text, state)
}
if (dirname)
{
free (dirname);
xfree (dirname);
dirname = (char *)NULL;
}
if (filename)
{
free (filename);
xfree (filename);
filename = (char *)NULL;
}
if (users_dirname)
{
free (users_dirname);
xfree (users_dirname);
users_dirname = (char *)NULL;
}
@ -2225,7 +2344,7 @@ rl_filename_completion_function (text, state)
temp = savestring (convfn);
if (convfn != dentry)
free (convfn);
xfree (convfn);
return (temp);
}
@ -2304,14 +2423,14 @@ rl_old_menu_complete (count, invoking_key)
if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
{
rl_ding ();
rl_ding ();
FREE (matches);
matches = (char **)0;
FREE (orig_text);
orig_text = (char *)0;
completion_changed_buffer = 0;
RL_UNSETSTATE(RL_STATE_COMPLETING);
return (0);
completion_changed_buffer = 0;
RL_UNSETSTATE(RL_STATE_COMPLETING);
return (0);
}
RL_UNSETSTATE(RL_STATE_COMPLETING);
@ -2340,7 +2459,10 @@ rl_old_menu_complete (count, invoking_key)
match_list_index += count;
if (match_list_index < 0)
match_list_index += match_list_size;
{
while (match_list_index < 0)
match_list_index += match_list_size;
}
else
match_list_index %= match_list_size;
@ -2375,7 +2497,7 @@ rl_menu_complete (count, ignore)
static int full_completion = 0; /* set to 1 if menu completion should reinitialize on next call */
static int orig_start, orig_end;
static char quote_char;
static int delimiter;
static int delimiter, cstate;
/* The first time through, we generate the list of matches and set things
up to insert them. */
@ -2428,14 +2550,14 @@ rl_menu_complete (count, ignore)
if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
{
rl_ding ();
rl_ding ();
FREE (matches);
matches = (char **)0;
FREE (orig_text);
orig_text = (char *)0;
completion_changed_buffer = 0;
RL_UNSETSTATE(RL_STATE_COMPLETING);
return (0);
completion_changed_buffer = 0;
RL_UNSETSTATE(RL_STATE_COMPLETING);
return (0);
}
RL_UNSETSTATE(RL_STATE_COMPLETING);
@ -2483,6 +2605,11 @@ rl_menu_complete (count, ignore)
full_completion = 1;
return (0);
}
else if (_rl_menu_complete_prefix_first && match_list_size > 1)
{
rl_ding ();
return (0);
}
}
/* Now we have the list of matches. Replace the text between
@ -2500,7 +2627,10 @@ rl_menu_complete (count, ignore)
match_list_index += count;
if (match_list_index < 0)
match_list_index += match_list_size;
{
while (match_list_index < 0)
match_list_index += match_list_size;
}
else
match_list_index %= match_list_size;

View file

@ -12,7 +12,7 @@ This document describes the GNU History library
a programming tool that provides a consistent user interface for
recalling lines of previously typed input.
Copyright @copyright{} 1988--2009 Free Software Foundation, Inc.
Copyright @copyright{} 1988--2011 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice

View file

@ -1,7 +1,7 @@
@ignore
This file documents the user interface to the GNU History library.
Copyright (C) 1988-2007 Free Software Foundation, Inc.
Copyright (C) 1988-2011 Free Software Foundation, Inc.
Authored by Brian Fox and Chet Ramey.
Permission is granted to make and distribute verbatim copies of this manual
@ -426,6 +426,10 @@ The maximum number of history entries. This must be changed using
If non-zero, timestamps are written to the history file, so they can be
preserved between sessions. The default value is 0, meaning that
timestamps are not saved.
The current timestamp format uses the value of @var{history_comment_char}
to delimit timestamp entries in the history file. If that variable does
not have a value (the default), timestamps will not be written.
@end deftypevar
@deftypevar char history_expansion_char

View file

@ -1,7 +1,7 @@
@ignore
This file documents the user interface to the GNU History library.
Copyright (C) 1988-2007 Free Software Foundation, Inc.
Copyright (C) 1988--2011 Free Software Foundation, Inc.
Authored by Brian Fox and Chet Ramey.
Permission is granted to make and distribute verbatim copies of this manual
@ -299,6 +299,8 @@ writing the history file.
An event designator is a reference to a command line entry in the
history list.
Unless the reference is absolute, events are relative to the current
position in the history list.
@cindex history events
@table @asis
@ -324,10 +326,15 @@ Refer to the command @var{n} lines back.
Refer to the previous command. This is a synonym for @samp{!-1}.
@item @code{!@var{string}}
Refer to the most recent command starting with @var{string}.
Refer to the most recent command
preceding the current position in the history list
starting with @var{string}.
@item @code{!?@var{string}[?]}
Refer to the most recent command containing @var{string}. The trailing
Refer to the most recent command
preceding the current position in the history list
containing @var{string}.
The trailing
@samp{?} may be omitted if the @var{string} is followed immediately by
a newline.

View file

@ -13,7 +13,7 @@ This manual describes the GNU Readline Library
consistency of user interface across discrete programs which provide
a command line interface.
Copyright @copyright{} 1988--2009 Free Software Foundation, Inc.
Copyright @copyright{} 1988--2011 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice

View file

@ -7,7 +7,7 @@ This document describes the GNU Readline Library, a utility for aiding
in the consistency of user interface across discrete programs that need
to provide a command line interface.
Copyright (C) 1988-2007 Free Software Foundation, Inc.
Copyright (C) 1988--2011 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@ -1157,6 +1157,9 @@ of strings, in argv format, such as a list of completion matches.
is the length of the longest string in @code{matches}. This function uses
the setting of @code{print-completions-horizontally} to select how the
matches are displayed (@pxref{Readline Init File Syntax}).
When displaying completions, this function sets the number of columns used
for display to the value of @code{completion-display-width}, the value of
the environment variable @env{COLUMNS}, or the screen width, in that order.
@end deftypefun
The following are implemented as macros, defined in @code{chardefs.h}.
@ -1714,18 +1717,20 @@ from the array must be freed.
@deftypevar {rl_icppfunc_t *} rl_directory_completion_hook
This function, if defined, is allowed to modify the directory portion
of filenames Readline completes. It is called with the address of a
string (the current directory name) as an argument, and may modify that string.
of filenames Readline completes.
It could be used to expand symbolic links or shell variables in pathnames.
It is called with the address of a string (the current directory name) as an
argument, and may modify that string.
If the string is replaced with a new string, the old value should be freed.
Any modified directory name should have a trailing slash.
The modified value will be displayed as part of the completion, replacing
The modified value will be used as part of the completion, replacing
the directory portion of the pathname the user typed.
It returns an integer that should be non-zero if the function modifies
its directory argument.
It could be used to expand symbolic links or shell variables in pathnames.
At the least, even if no other expansion is performed, this function should
remove any quote characters from the directory name, because its result will
be passed directly to @code{opendir()}.
The directory completion hook returns an integer that should be non-zero if
the function modifies its directory argument.
The function should not modify the directory argument if it returns 0.
@end deftypevar
@ignore
@ -1737,7 +1742,7 @@ it only modifies the directory name used in @code{opendir}, not what is
displayed when the possible completions are printed or inserted. It is
called before rl_directory_completion_hook.
I'm not happy with how this worksyet, so it's undocumented.
I'm not happy with how this works yet, so it's undocumented.
@end deftypevar
@end ignore

View file

@ -9,7 +9,7 @@ use these features. There is a document entitled "readline.texinfo"
which contains both end-user and programmer documentation for the
GNU Readline Library.
Copyright (C) 1988--2009 Free Software Foundation, Inc.
Copyright (C) 1988--2011 Free Software Foundation, Inc.
Authored by Brian Fox and Chet Ramey.
@ -51,7 +51,7 @@ Command line editing is enabled by default when using an interactive shell,
unless the @option{--noediting} option is supplied at shell invocation.
Line editing is also used when using the @option{-e} option to the
@code{read} builtin command (@pxref{Bash Builtins}).
By default, the line editing commands are similar to those of emacs.
By default, the line editing commands are similar to those of Emacs.
A vi-style line editing interface is also available.
Line editing can be enabled at any time using the @option{-o emacs} or
@option{-o vi} options to the @code{set} builtin command
@ -431,11 +431,27 @@ The string to insert at the beginning of the line when the
@code{insert-comment} command is executed. The default value
is @code{"#"}.
@item completion-display-width
@vindex completion-display-width
The number of screen columns used to display possible matches
when performing completion.
The value is ignored if it is less than 0 or greater than the terminal
screen width.
A value of 0 will cause matches to be displayed one per line.
The default value is -1.
@item completion-ignore-case
@vindex completion-ignore-case
If set to @samp{on}, Readline performs filename matching and completion
in a case-insensitive fashion.
The default value is @samp{off}.
@item completion-map-case
@vindex completion-map-case
If set to @samp{on}, and @var{completion-ignore-case} is enabled, Readline
treats hyphens (@samp{-}) and underscores (@samp{_}) as equivalent when
performing case-insensitive filename matching and completion.
@item completion-prefix-display-length
@vindex completion-prefix-display-length
The length in characters of the common prefix of a list of possible
@ -570,10 +586,17 @@ The default is @samp{off}.
@vindex match-hidden-files
This variable, when set to @samp{on}, causes Readline to match files whose
names begin with a @samp{.} (hidden files) when performing filename
completion, unless the leading @samp{.} is
completion.
If set to @samp{off}, the leading @samp{.} must be
supplied by the user in the filename to be completed.
This variable is @samp{on} by default.
@item menu-complete-display-prefix
@vindex menu-complete-display-prefix
If set to @samp{on}, menu completion displays the common prefix of the
list of possible completions (which may be empty) before cycling through
the list. The default is @samp{off}.
@item output-meta
@vindex output-meta
If set to @samp{on}, Readline will display characters with the
@ -1097,10 +1120,14 @@ as if the @samp{!@var{n}} history expansion had been specified.
@item yank-last-arg (M-. or M-_)
Insert last argument to the previous command (the last word of the
previous history entry). With an
argument, behave exactly like @code{yank-nth-arg}.
previous history entry).
With a numeric argument, behave exactly like @code{yank-nth-arg}.
Successive calls to @code{yank-last-arg} move back through the history
list, inserting the last argument of each line in turn.
list, inserting the last word (or the word specified by the argument to
the first call) of each line in turn.
Any numeric argument supplied to these successive calls determines
the direction to move through the history. A negative argument switches
the direction through the history (back or forward).
The history expansion facilities are used to extract the last argument,
as if the @samp{!$} history expansion had been specified.
@ -1212,7 +1239,7 @@ Kill from point to the end of the current word, or if between
words, to the end of the next word.
Word boundaries are the same as @code{shell-forward-word}.
@item backward-kill-word ()
@item shell-backward-kill-word ()
Kill the word behind point.
Word boundaries are the same as @code{shell-backward-word}.
@end ifset
@ -1298,6 +1325,9 @@ The default is filename completion.
@item possible-completions (M-?)
List the possible completions of the text before point.
When displaying completions, Readline sets the number of columns used
for display to the value of @code{completion-display-width}, the value of
the environment variable @env{COLUMNS}, or the screen width, in that order.
@item insert-completions (M-*)
Insert all completions of the text before point that would have
@ -1579,7 +1609,7 @@ editing mode.
While the Readline library does not have a full set of @code{vi}
editing functions, it does contain enough to allow simple editing
of the line. The Readline @code{vi} mode behaves as specified in
the @sc{posix} 1003.2 standard.
the @sc{posix} standard.
@ifset BashFeatures
In order to switch interactively between @code{emacs} and @code{vi}
@ -1733,7 +1763,7 @@ exit status of 124. If a shell function returns 124, and changes
the compspec associated with the command on which completion is being
attempted (supplied as the first argument when the function is executed),
programmable completion restarts from the beginning, with an
attempt to find a compspec for that command. This allows a set of
attempt to find a new compspec for that command. This allows a set of
completions to be built dynamically as completion is attempted, rather than
being loaded all at once.
@ -1933,17 +1963,6 @@ User names. May also be specified as @option{-u}.
Names of all shell variables. May also be specified as @option{-v}.
@end table
@item -G @var{globpat}
The filename expansion pattern @var{globpat} is expanded to generate
the possible completions.
@item -W @var{wordlist}
The @var{wordlist} is split using the characters in the
@env{IFS} special variable as delimiters, and each resultant word
is expanded.
The possible completions are the members of the resultant list which
match the word being completed.
@item -C @var{command}
@var{command} is executed in a subshell environment, and its output is
used as the possible completions.
@ -1954,13 +1973,9 @@ environment.
When it finishes, the possible completions are retrieved from the value
of the @env{COMPREPLY} array variable.
@item -X @var{filterpat}
@var{filterpat} is a pattern as used for filename expansion.
It is applied to the list of possible completions generated by the
preceding options and arguments, and each completion matching
@var{filterpat} is removed from the list.
A leading @samp{!} in @var{filterpat} negates the pattern; in this
case, any completion not matching @var{filterpat} is removed.
@item -G @var{globpat}
The filename expansion pattern @var{globpat} is expanded to generate
the possible completions.
@item -P @var{prefix}
@var{prefix} is added at the beginning of each possible completion
@ -1969,6 +1984,21 @@ after all other options have been applied.
@item -S @var{suffix}
@var{suffix} is appended to each possible completion
after all other options have been applied.
@item -W @var{wordlist}
The @var{wordlist} is split using the characters in the
@env{IFS} special variable as delimiters, and each resultant word
is expanded.
The possible completions are the members of the resultant list which
match the word being completed.
@item -X @var{filterpat}
@var{filterpat} is a pattern as used for filename expansion.
It is applied to the list of possible completions generated by the
preceding options and arguments, and each completion matching
@var{filterpat} is removed from the list.
A leading @samp{!} in @var{filterpat} negates the pattern; in this
case, any completion not matching @var{filterpat} is removed.
@end table
The return value is true unless an invalid option is supplied, an option
@ -1983,7 +2013,7 @@ an error occurs adding a completion specification.
@code{compopt} [-o @var{option}] [-DE] [+o @var{option}] [@var{name}]
@end example
Modify completion options for each @var{name} according to the
@var{option}s, or for the currently-execution completion if no @var{name}s
@var{option}s, or for the currently-executing completion if no @var{name}s
are supplied.
If no @var{option}s are given, display the completion options for each
@var{name} or the current completion.

View file

@ -12,7 +12,7 @@ This manual describes the end user interface of the GNU Readline Library
consistency of user interface across discrete programs which provide
a command line interface.
Copyright @copyright{} 1988--2009 Free Software Foundation, Inc.
Copyright @copyright{} 1988--2011 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice

View file

@ -1,10 +1,10 @@
@ignore
Copyright (C) 1988-2009 Free Software Foundation, Inc.
Copyright (C) 1988-2011 Free Software Foundation, Inc.
@end ignore
@set EDITION 6.1
@set VERSION 6.1
@set UPDATED 9 October 2009
@set UPDATED-MONTH October 2009
@set EDITION 6.2
@set VERSION 6.2
@set UPDATED September 6 2010
@set UPDATED-MONTH September 2010
@set LASTCHANGE Fri Oct 9 12:57:58 EDT 2009
@set LASTCHANGE Mon Sep 6 22:07:10 EDT 2010

View file

@ -1,6 +1,6 @@
/* funmap.c -- attach names to functions. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2010 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.
@ -148,6 +148,8 @@ static const FUNMAP default_funmap[] = {
{ "vi-append-mode", rl_vi_append_mode },
{ "vi-arg-digit", rl_vi_arg_digit },
{ "vi-back-to-indent", rl_vi_back_to_indent },
{ "vi-backward-bigword", rl_vi_bWord },
{ "vi-backward-word", rl_vi_bword },
{ "vi-bWord", rl_vi_bWord },
{ "vi-bword", rl_vi_bword },
{ "vi-change-case", rl_vi_change_case },
@ -160,12 +162,15 @@ static const FUNMAP default_funmap[] = {
{ "vi-delete-to", rl_vi_delete_to },
{ "vi-eWord", rl_vi_eWord },
{ "vi-editing-mode", rl_vi_editing_mode },
{ "vi-end-bigword", rl_vi_eWord },
{ "vi-end-word", rl_vi_end_word },
{ "vi-eof-maybe", rl_vi_eof_maybe },
{ "vi-eword", rl_vi_eword },
{ "vi-fWord", rl_vi_fWord },
{ "vi-fetch-history", rl_vi_fetch_history },
{ "vi-first-print", rl_vi_first_print },
{ "vi-forward-bigword", rl_vi_fWord },
{ "vi-forward-word", rl_vi_fword },
{ "vi-fword", rl_vi_fword },
{ "vi-goto-mark", rl_vi_goto_mark },
{ "vi-insert-beg", rl_vi_insert_beg },

View file

@ -1,6 +1,6 @@
/* histexpand.c -- history expansion. */
/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
/* Copyright (C) 1989-2010 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@ -245,7 +245,7 @@ get_history_event (string, caller_index, delimiting_quote)
#define FAIL_SEARCH() \
do { \
history_offset = history_length; free (temp) ; return (char *)NULL; \
history_offset = history_length; xfree (temp) ; return (char *)NULL; \
} while (0)
/* If there is no search string, try to use the previous search string,
@ -254,7 +254,7 @@ get_history_event (string, caller_index, delimiting_quote)
{
if (search_string)
{
free (temp);
xfree (temp);
temp = savestring (search_string);
}
else
@ -285,7 +285,7 @@ get_history_event (string, caller_index, delimiting_quote)
search_match = history_find_word (entry->line, local_index);
}
else
free (temp);
xfree (temp);
return (entry->line);
}
@ -508,7 +508,7 @@ postproc_subst_rhs ()
}
}
new[j] = '\0';
free (subst_rhs);
xfree (subst_rhs);
subst_rhs = new;
subst_rhs_len = j;
}
@ -585,7 +585,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
if (event == 0)
{
*ret_string = hist_error (string, start, i, EVENT_NOT_FOUND);
free (result);
xfree (result);
return (-1);
}
@ -599,7 +599,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
if (word_spec == (char *)&error_pointer)
{
*ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC);
free (result);
xfree (result);
return (-1);
}
@ -632,8 +632,8 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
{
default:
*ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER);
free (result);
free (temp);
xfree (result);
xfree (temp);
return -1;
case 'q':
@ -658,7 +658,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
{
tstr++;
t = savestring (tstr);
free (temp);
xfree (temp);
temp = t;
}
break;
@ -683,7 +683,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
if (tstr)
{
t = savestring (tstr);
free (temp);
xfree (temp);
temp = t;
}
break;
@ -759,8 +759,8 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
if (subst_lhs_len == 0)
{
*ret_string = hist_error (string, starting_index, i, NO_PREV_SUBST);
free (result);
free (temp);
xfree (result);
xfree (temp);
return -1;
}
@ -769,8 +769,8 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
if (subst_lhs_len > l_temp)
{
*ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
free (result);
free (temp);
xfree (result);
xfree (temp);
return (-1);
}
@ -811,7 +811,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
temp + si + subst_lhs_len,
l_temp - (si + subst_lhs_len));
new_event[len] = '\0';
free (temp);
xfree (temp);
temp = new_event;
failed = 0;
@ -847,8 +847,8 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
continue; /* don't want to increment i */
*ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
free (result);
free (temp);
xfree (result);
xfree (temp);
return (-1);
}
}
@ -869,7 +869,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
else
x = savestring (temp);
free (temp);
xfree (temp);
temp = x;
}
@ -877,7 +877,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
if (n >= result_len)
result = (char *)xrealloc (result, n + 2);
strcpy (result, temp);
free (temp);
xfree (temp);
*end_index_ptr = i;
*ret_string = result;
@ -1064,7 +1064,7 @@ history_expand (hstring, output)
if (string[i] != history_expansion_char)
{
free (result);
xfree (result);
*output = savestring (string);
return (0);
}
@ -1144,7 +1144,7 @@ history_expand (hstring, output)
strncpy (temp, string + quote, slen);
temp[slen - 1] = '\0';
ADD_STRING (temp);
free (temp);
xfree (temp);
}
else
ADD_CHAR (string[i]);
@ -1157,7 +1157,7 @@ history_expand (hstring, output)
temp = (char *)xmalloc (l - i + 1);
strcpy (temp, string + i);
ADD_STRING (temp);
free (temp);
xfree (temp);
i = l;
}
else
@ -1190,7 +1190,7 @@ history_expand (hstring, output)
temp = (char *)xmalloc (1 + strlen (result));
strcpy (temp, result);
ADD_STRING (temp);
free (temp);
xfree (temp);
}
i++;
break;
@ -1201,9 +1201,9 @@ history_expand (hstring, output)
if (r < 0)
{
*output = temp;
free (result);
xfree (result);
if (string != hstring)
free (string);
xfree (string);
return -1;
}
else
@ -1213,7 +1213,7 @@ history_expand (hstring, output)
modified++;
if (*temp)
ADD_STRING (temp);
free (temp);
xfree (temp);
}
only_printing = r == 1;
i = eindex;
@ -1224,7 +1224,7 @@ history_expand (hstring, output)
*output = result;
if (string != hstring)
free (string);
xfree (string);
if (only_printing)
{
@ -1405,8 +1405,8 @@ history_arg_extract (first, last, string)
}
for (i = 0; i < len; i++)
free (list[i]);
free (list);
xfree (list[i]);
xfree (list);
return (result);
}
@ -1417,10 +1417,10 @@ history_tokenize_word (string, ind)
int ind;
{
register int i;
int delimiter;
int delimiter, nestdelim, delimopen;
i = ind;
delimiter = 0;
delimiter = nestdelim = 0;
if (member (string[i], "()\n"))
{
@ -1442,13 +1442,21 @@ history_tokenize_word (string, ind)
return i;
}
else if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
(peek == '>' && string[i] == '&') ||
(peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */
(peek == '(' && string[i] == '$')) /* ) */
(peek == '>' && string[i] == '&'))
{
i += 2;
return i;
}
/* XXX - separated out for later -- bash-4.2 */
else if ((peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */
(peek == '(' && string[i] == '$')) /*)*/
{
i += 2;
delimopen = '(';
delimiter = ')';
nestdelim = 1;
goto get_word;
}
#if 0
else if (peek == '\'' && string[i] == '$')
{
@ -1464,9 +1472,25 @@ history_tokenize_word (string, ind)
}
}
/* same code also used for $(...)/<(...)/>(...) above */
if (member (string[i], "!@?+*"))
{
int peek = string[i + 1];
if (peek == '(') /*)*/
{
/* Shell extended globbing patterns */
i += 2;
delimopen = '(';
delimiter = ')'; /* XXX - not perfect */
nestdelim = 1;
}
}
get_word:
/* Get word from string + i; */
if (member (string[i], HISTORY_QUOTE_CHARACTERS))
if (delimiter == 0 && member (string[i], HISTORY_QUOTE_CHARACTERS))
delimiter = string[i++];
for (; string[i]; i++)
@ -1484,16 +1508,31 @@ history_tokenize_word (string, ind)
continue;
}
/* delimiter must be set and set to something other than a quote if
nestdelim is set, so these tests are safe. */
if (nestdelim && string[i] == delimopen)
{
nestdelim++;
continue;
}
if (nestdelim && string[i] == delimiter)
{
nestdelim--;
if (nestdelim == 0)
delimiter = 0;
continue;
}
if (delimiter && string[i] == delimiter)
{
delimiter = 0;
continue;
}
if (!delimiter && (member (string[i], history_word_delimiters)))
if (delimiter == 0 && (member (string[i], history_word_delimiters)))
break;
if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
if (delimiter == 0 && member (string[i], HISTORY_QUOTE_CHARACTERS))
delimiter = string[i];
}
@ -1590,7 +1629,7 @@ freewords (words, start)
register int i;
for (i = start; words[i]; i++)
free (words[i]);
xfree (words[i]);
}
/* Find and return the word which contains the character at index IND
@ -1614,8 +1653,8 @@ history_find_word (line, ind)
}
s = words[wind];
for (i = 0; i < wind; i++)
free (words[i]);
xfree (words[i]);
freewords (words, wind + 1);
free (words);
xfree (words);
return s;
}

View file

@ -1,6 +1,6 @@
/* histfile.c - functions to manipulate the history file. */
/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
/* Copyright (C) 1989-2010 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@ -126,8 +126,12 @@ history_filename (filename)
if (home == 0)
{
#if 0
home = ".";
home_len = 1;
#else
return (NULL);
#endif
}
else
home_len = strlen (home);
@ -179,7 +183,7 @@ read_history_range (filename, from, to)
buffer = last_ts = (char *)NULL;
input = history_filename (filename);
file = open (input, O_RDONLY|O_BINARY, 0666);
file = input ? open (input, O_RDONLY|O_BINARY, 0666) : -1;
if ((file < 0) || (fstat (file, &finfo) == -1))
goto error_and_exit;
@ -314,7 +318,7 @@ history_truncate_file (fname, lines)
buffer = (char *)NULL;
filename = history_filename (fname);
file = open (filename, O_RDONLY|O_BINARY, 0666);
file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1;
rv = 0;
/* Don't try to truncate non-regular files. */
@ -413,7 +417,7 @@ history_truncate_file (fname, lines)
FREE (buffer);
free (filename);
xfree (filename);
return rv;
}
@ -436,9 +440,10 @@ history_do_write (filename, nelements, overwrite)
mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
#endif
output = history_filename (filename);
file = output ? open (output, mode, 0600) : -1;
rv = 0;
if ((file = open (output, mode, 0600)) == -1)
if (file == -1)
{
FREE (output);
return (errno);
@ -515,7 +520,7 @@ mmap_error:
#else
if (write (file, buffer, buffer_size) < 0)
rv = errno;
free (buffer);
xfree (buffer);
#endif
}

View file

@ -338,7 +338,7 @@ free_history_entry (hist)
FREE (hist->line);
FREE (hist->timestamp);
x = hist->data;
free (hist);
xfree (hist);
return (x);
}

View file

@ -1,6 +1,6 @@
/* input.c -- character input functions for readline. */
/* Copyright (C) 1994-2009 Free Software Foundation, Inc.
/* Copyright (C) 1994-2010 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.
@ -427,17 +427,19 @@ rl_read_key ()
/* If the user has an event function, then call it periodically. */
if (rl_event_hook)
{
while (rl_event_hook && rl_get_char (&c) == 0)
while (rl_event_hook)
{
(*rl_event_hook) ();
RL_CHECK_SIGNALS ();
if (rl_done) /* XXX - experimental */
return ('\n');
if (rl_gather_tyi () < 0) /* XXX - EIO */
{
rl_done = 1;
return ('\n');
}
RL_CHECK_SIGNALS ();
if (rl_get_char (&c) != 0)
break;
if (rl_done) /* XXX - experimental */
return ('\n');
(*rl_event_hook) ();
}
}
else

View file

@ -104,6 +104,9 @@ _rl_scxt_alloc (type, flags)
cxt->save_undo_list = 0;
cxt->keymap = _rl_keymap;
cxt->okeymap = _rl_keymap;
cxt->history_pos = 0;
cxt->direction = 0;
@ -336,10 +339,22 @@ _rl_isearch_dispatch (cxt, c)
return -1;
}
/* Translate the keys we do something with to opcodes. */
if (c >= 0 && _rl_keymap[c].type == ISFUNC)
/* If we are moving into a new keymap, modify cxt->keymap and go on.
This can be a problem if c == ESC and we want to terminate the
incremental search, so we check */
if (c >= 0 && cxt->keymap[c].type == ISKMAP && strchr (cxt->search_terminators, cxt->lastc) == 0)
{
f = _rl_keymap[c].function;
cxt->keymap = FUNCTION_TO_KEYMAP (cxt->keymap, c);
cxt->sflags |= SF_CHGKMAP;
/* XXX - we should probably save this sequence, so we can do
something useful if this doesn't end up mapping to a command. */
return 1;
}
/* Translate the keys we do something with to opcodes. */
if (c >= 0 && cxt->keymap[c].type == ISFUNC)
{
f = cxt->keymap[c].function;
if (f == rl_reverse_search_history)
cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2;
@ -347,19 +362,27 @@ _rl_isearch_dispatch (cxt, c)
cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1;
else if (f == rl_rubout)
cxt->lastc = -3;
else if (c == CTRL ('G'))
else if (c == CTRL ('G') || f == rl_abort)
cxt->lastc = -4;
else if (c == CTRL ('W')) /* XXX */
else if (c == CTRL ('W') || f == rl_unix_word_rubout) /* XXX */
cxt->lastc = -5;
else if (c == CTRL ('Y')) /* XXX */
else if (c == CTRL ('Y') || f == rl_yank) /* XXX */
cxt->lastc = -6;
}
/* If we changed the keymap earlier while translating a key sequence into
a command, restore it now that we've succeeded. */
if (cxt->sflags & SF_CHGKMAP)
{
cxt->keymap = cxt->okeymap;
cxt->sflags &= ~SF_CHGKMAP;
}
/* The characters in isearch_terminators (set from the user-settable
variable isearch-terminators) are used to terminate the search but
not subsequently execute the character as a command. The default
value is "\033\012" (ESC and C-J). */
if (strchr (cxt->search_terminators, cxt->lastc))
if (cxt->lastc > 0 && strchr (cxt->search_terminators, cxt->lastc))
{
/* ESC still terminates the search, but if there is pending
input or if input arrives within 0.1 seconds (on systems

View file

@ -142,11 +142,11 @@ rl_discard_keymap (map)
case ISKMAP:
rl_discard_keymap ((Keymap)map[i].function);
free ((char *)map[i].function);
xfree ((char *)map[i].function);
break;
case ISMACR:
free ((char *)map[i].function);
xfree ((char *)map[i].function);
break;
}
}
@ -158,5 +158,5 @@ rl_free_keymap (map)
Keymap map;
{
rl_discard_keymap (map);
free ((char *)map);
xfree ((char *)map);
}

View file

@ -52,11 +52,6 @@ typedef struct _keymap_entry {
#define KEYMAP_SIZE 257
#define ANYOTHERKEY KEYMAP_SIZE-1
/* I wanted to make the above structure contain a union of:
union { rl_command_func_t *function; struct _keymap_entry *keymap; } value;
but this made it impossible for me to create a static array.
Maybe I need C lessons. */
typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE];
typedef KEYMAP_ENTRY *Keymap;

View file

@ -147,7 +147,7 @@ _rl_copy_to_kill_ring (text, append)
strcat (new, old);
}
xfree (old);
free (text);
xfree (text);
rl_kill_ring[slot] = new;
}
else
@ -601,7 +601,7 @@ rl_yank_nth_arg_internal (count, ignore, history_skip)
#endif /* VI_MODE */
rl_insert_text (arg);
free (arg);
xfree (arg);
rl_end_undo_group ();
return 0;
@ -640,7 +640,7 @@ rl_yank_last_arg (count, key)
{
if (undo_needed)
rl_do_undo ();
if (count < 1)
if (count < 0) /* XXX - was < 1 */
direction = -direction;
history_skip += direction;
if (history_skip < 0)

View file

@ -328,7 +328,7 @@ _rl_free_history_entry (entry)
FREE (entry->line);
FREE (entry->timestamp);
free (entry);
xfree (entry);
}
/* Perhaps put back the current line if it has changed. */
@ -342,9 +342,9 @@ rl_maybe_replace_line ()
if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
{
temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
free (temp->line);
xfree (temp->line);
FREE (temp->timestamp);
free (temp);
xfree (temp);
}
return 0;
}
@ -480,7 +480,7 @@ _rl_revert_all_lines ()
_rl_set_the_line ();
/* and clean up */
free (lbuf);
xfree (lbuf);
}
/* **************************************************************** */

View file

@ -145,7 +145,7 @@ _rl_init_eightbit ()
_rl_output_meta_chars = 1;
break;
}
free (t);
xfree (t);
return (legal_lang_values[i] ? 1 : 0);
#endif /* !HAVE_SETLOCALE */

View file

@ -0,0 +1,47 @@
/* posixselect.h -- wrapper for select(2) includes and definitions */
/* Copyright (C) 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/>.
*/
#ifndef _POSIXSELECT_H_
#define _POSIXSELECT_H_
#if defined (FD_SET) && !defined (HAVE_SELECT)
# define HAVE_SELECT 1
#endif
#if defined (HAVE_SELECT)
# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX)
# include <sys/time.h>
# endif
#endif /* HAVE_SELECT */
#if defined (HAVE_SYS_SELECT_H)
# include <sys/select.h>
#endif
#ifndef USEC_PER_SEC
# define USEC_PER_SEC 1000000
#endif
#define USEC_TO_TIMEVAL(us, tv) \
do { \
(tv).tv_sec = (us) / USEC_PER_SEC; \
(tv).tv_usec = (us) % USEC_PER_SEC; \
} while (0)
#endif /* _POSIXSELECT_H_ */

View file

@ -382,7 +382,7 @@ readline_internal_setup ()
nprompt = _rl_strip_prompt (rl_prompt);
fprintf (_rl_out_stream, "%s", nprompt);
fflush (_rl_out_stream);
free (nprompt);
xfree (nprompt);
}
}
else
@ -426,7 +426,7 @@ readline_internal_teardown (eof)
_rl_free_history_entry (entry);
strcpy (the_line, temp);
free (temp);
xfree (temp);
}
if (_rl_revert_all_at_newline)
@ -629,7 +629,7 @@ void
_rl_keyseq_cxt_dispose (cxt)
_rl_keyseq_cxt *cxt;
{
free (cxt);
xfree (cxt);
}
void

View file

@ -1,6 +1,6 @@
/* Readline.h -- the names of functions callable from within readline. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2011 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.
@ -39,9 +39,9 @@ extern "C" {
#endif
/* Hex-encoded Readline version number. */
#define RL_READLINE_VERSION 0x0600 /* Readline 6.0 */
#define RL_READLINE_VERSION 0x0602 /* Readline 6.2 */
#define RL_VERSION_MAJOR 6
#define RL_VERSION_MINOR 0
#define RL_VERSION_MINOR 2
/* Readline data structures. */
@ -666,16 +666,24 @@ extern const char *rl_special_prefixes;
completing on a directory name. The function is called with
the address of a string (the current directory name) as an arg. It
changes what is displayed when the possible completions are printed
or inserted. */
or inserted. The directory completion hook should perform
any necessary dequoting. This function should return 1 if it modifies
the directory name pointer passed as an argument. If the directory
completion hook returns 0, it should not modify the directory name
pointer passed as an argument. */
extern rl_icppfunc_t *rl_directory_completion_hook;
/* If non-zero, this is the address of a function to call when completing
a directory name. This function takes the address of the directory name
to be modified as an argument. Unlike rl_directory_completion_hook, it
only modifies the directory name used in opendir(2), not what is displayed
when the possible completions are printed or inserted. It is called
before rl_directory_completion_hook. I'm not happy with how this works
yet, so it's undocumented. */
when the possible completions are printed or inserted. If set, it takes
precedence over rl_directory_completion_hook. The directory rewrite
hook should perform any necessary dequoting. This function has the same
return value properties as the directory_completion_hook.
I'm not happy with how this works yet, so it's undocumented. I'm trying
it in bash to see how well it goes. */
extern rl_icppfunc_t *rl_directory_rewrite_hook;
/* If non-zero, this is the address of a function to call when reading
@ -805,30 +813,30 @@ extern int rl_inhibit_completion;
/* Possible state values for rl_readline_state */
#define RL_STATE_NONE 0x000000 /* no state; before first call */
#define RL_STATE_INITIALIZING 0x000001 /* initializing */
#define RL_STATE_INITIALIZED 0x000002 /* initialization done */
#define RL_STATE_TERMPREPPED 0x000004 /* terminal is prepped */
#define RL_STATE_READCMD 0x000008 /* reading a command key */
#define RL_STATE_METANEXT 0x000010 /* reading input after ESC */
#define RL_STATE_DISPATCHING 0x000020 /* dispatching to a command */
#define RL_STATE_MOREINPUT 0x000040 /* reading more input in a command function */
#define RL_STATE_ISEARCH 0x000080 /* doing incremental search */
#define RL_STATE_NSEARCH 0x000100 /* doing non-inc search */
#define RL_STATE_SEARCH 0x000200 /* doing a history search */
#define RL_STATE_NUMERICARG 0x000400 /* reading numeric argument */
#define RL_STATE_MACROINPUT 0x000800 /* getting input from a macro */
#define RL_STATE_MACRODEF 0x001000 /* defining keyboard macro */
#define RL_STATE_OVERWRITE 0x002000 /* overwrite mode */
#define RL_STATE_COMPLETING 0x004000 /* doing completion */
#define RL_STATE_SIGHANDLER 0x008000 /* in readline sighandler */
#define RL_STATE_UNDOING 0x010000 /* doing an undo */
#define RL_STATE_INPUTPENDING 0x020000 /* rl_execute_next called */
#define RL_STATE_TTYCSAVED 0x040000 /* tty special chars saved */
#define RL_STATE_CALLBACK 0x080000 /* using the callback interface */
#define RL_STATE_VIMOTION 0x100000 /* reading vi motion arg */
#define RL_STATE_MULTIKEY 0x200000 /* reading multiple-key command */
#define RL_STATE_VICMDONCE 0x400000 /* entered vi command mode at least once */
#define RL_STATE_REDISPLAYING 0x800000 /* updating terminal display */
#define RL_STATE_INITIALIZING 0x0000001 /* initializing */
#define RL_STATE_INITIALIZED 0x0000002 /* initialization done */
#define RL_STATE_TERMPREPPED 0x0000004 /* terminal is prepped */
#define RL_STATE_READCMD 0x0000008 /* reading a command key */
#define RL_STATE_METANEXT 0x0000010 /* reading input after ESC */
#define RL_STATE_DISPATCHING 0x0000020 /* dispatching to a command */
#define RL_STATE_MOREINPUT 0x0000040 /* reading more input in a command function */
#define RL_STATE_ISEARCH 0x0000080 /* doing incremental search */
#define RL_STATE_NSEARCH 0x0000100 /* doing non-inc search */
#define RL_STATE_SEARCH 0x0000200 /* doing a history search */
#define RL_STATE_NUMERICARG 0x0000400 /* reading numeric argument */
#define RL_STATE_MACROINPUT 0x0000800 /* getting input from a macro */
#define RL_STATE_MACRODEF 0x0001000 /* defining keyboard macro */
#define RL_STATE_OVERWRITE 0x0002000 /* overwrite mode */
#define RL_STATE_COMPLETING 0x0004000 /* doing completion */
#define RL_STATE_SIGHANDLER 0x0008000 /* in readline sighandler */
#define RL_STATE_UNDOING 0x0010000 /* doing an undo */
#define RL_STATE_INPUTPENDING 0x0020000 /* rl_execute_next called */
#define RL_STATE_TTYCSAVED 0x0040000 /* tty special chars saved */
#define RL_STATE_CALLBACK 0x0080000 /* using the callback interface */
#define RL_STATE_VIMOTION 0x0100000 /* reading vi motion arg */
#define RL_STATE_MULTIKEY 0x0200000 /* reading multiple-key command */
#define RL_STATE_VICMDONCE 0x0400000 /* entered vi command mode at least once */
#define RL_STATE_REDISPLAYING 0x0800000 /* updating terminal display */
#define RL_STATE_DONE 0x1000000 /* done; accepted line */

View file

@ -1,7 +1,7 @@
/* rlprivate.h -- functions and variables global to the readline library,
but not intended for use by applications. */
/* Copyright (C) 1999-2009 Free Software Foundation, Inc.
/* Copyright (C) 1999-2010 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.
@ -56,6 +56,7 @@
#define SF_REVERSE 0x01
#define SF_FOUND 0x02
#define SF_FAILED 0x04
#define SF_CHGKMAP 0x08
typedef struct __rl_search_context
{
@ -79,6 +80,9 @@ typedef struct __rl_search_context
UNDO_LIST *save_undo_list;
Keymap keymap; /* used when dispatching commands in search string */
Keymap okeymap; /* original keymap */
int history_pos;
int direction;
@ -120,7 +124,28 @@ typedef struct __rl_keyseq_context
int childval;
} _rl_keyseq_cxt;
/* fill in more as needed */
/* vi-mode commands that use result of motion command to define boundaries */
#define VIM_DELETE 0x01
#define VIM_CHANGE 0x02
#define VIM_YANK 0x04
/* various states for vi-mode commands that use motion commands. reflects
RL_READLINE_STATE */
#define VMSTATE_READ 0x01
#define VMSTATE_NUMARG 0x02
typedef struct __rl_vimotion_context
{
int op;
int state;
int flags; /* reserved */
_rl_arg_cxt ncxt;
int numeric_arg;
int start, end; /* rl_point, rl_end */
int key, motion; /* initial key, motion command */
} _rl_vimotion_cxt;
/* fill in more as needed */
/* `Generic' callback data and functions */
typedef struct __rl_callback_generic_arg
{
@ -320,6 +345,7 @@ extern void _rl_set_cursor PARAMS((int, int));
/* text.c */
extern void _rl_fix_point PARAMS((int));
extern int _rl_replace_text PARAMS((const char *, int, int));
extern int _rl_forward_char_internal PARAMS((int));
extern int _rl_insert_char PARAMS((int, int));
extern int _rl_overwrite_char PARAMS((int, int));
extern int _rl_overwrite_rubout PARAMS((int, int));
@ -366,6 +392,7 @@ extern void _rl_vi_reset_last PARAMS((void));
extern void _rl_vi_set_last PARAMS((int, int, int));
extern int _rl_vi_textmod_command PARAMS((int));
extern void _rl_vi_done_inserting PARAMS((void));
extern int _rl_vi_domove_callback PARAMS((_rl_vimotion_cxt *));
/*************************************************************************
* Undocumented private variables *
@ -385,11 +412,14 @@ extern int _rl_complete_show_unmodified;
extern int _rl_complete_mark_directories;
extern int _rl_complete_mark_symlink_dirs;
extern int _rl_completion_prefix_display_length;
extern int _rl_completion_columns;
extern int _rl_print_completions_horizontally;
extern int _rl_completion_case_fold;
extern int _rl_completion_case_map;
extern int _rl_match_hidden_files;
extern int _rl_page_completions;
extern int _rl_skip_completed_text;
extern int _rl_menu_complete_prefix_first;
/* display.c */
extern int _rl_vis_botlin;
@ -471,5 +501,6 @@ extern int _rl_undo_group_level;
/* vi_mode.c */
extern int _rl_vi_last_command;
extern _rl_vimotion_cxt *_rl_vimvcxt;
#endif /* _RL_PRIVATE_H_ */

View file

@ -604,7 +604,7 @@ rl_prep_terminal (meta_flag)
/* Try to keep this function from being INTerrupted. */
_rl_block_sigint ();
tty = fileno (rl_instream);
tty = rl_instream ? fileno (rl_instream) : fileno (stdin);
if (get_tty_settings (tty, &tio) < 0)
{
@ -678,7 +678,7 @@ rl_deprep_terminal ()
/* Try to keep this function from being interrupted. */
_rl_block_sigint ();
tty = fileno (rl_instream);
tty = rl_instream ? fileno (rl_instream) : fileno (stdout);
if (_rl_enable_keypad)
_rl_control_keypad (0);

View file

@ -33,5 +33,9 @@ char *
savestring (s)
const char *s;
{
return ((char *)strcpy ((char *)xmalloc (1 + strlen (s)), (s)));
char *ret;
ret = (char *)xmalloc (strlen (s) + 1);
strcpy (ret, s);
return ret;
}

View file

@ -211,7 +211,7 @@ _rl_nsearch_init (dir, pchar)
p = _rl_make_prompt_for_search (pchar ? pchar : ':');
rl_message ("%s", p, 0);
free (p);
xfree (p);
RL_SETSTATE(RL_STATE_NSEARCH);

View file

@ -130,12 +130,12 @@ sh_set_lines_and_columns (lines, cols)
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
sprintf (b, "%d", lines);
setenv ("LINES", b, 1);
free (b);
xfree (b);
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
sprintf (b, "%d", cols);
setenv ("COLUMNS", b, 1);
free (b);
xfree (b);
#else /* !HAVE_SETENV */
# if defined (HAVE_PUTENV)
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("LINES=") + 1);

View file

@ -131,6 +131,7 @@ static sighandler_cxt old_winch;
/* Called from RL_CHECK_SIGNALS() macro */
RETSIGTYPE
_rl_signal_handler (sig)
int sig;
{
_rl_caught_signal = 0; /* XXX */

View file

@ -96,12 +96,12 @@ static char *term_string_buffer = (char *)NULL;
static int tcap_initialized;
#if !defined (__linux__)
#if !defined (__linux__) && !defined (NCURSES_VERSION)
# if defined (__EMX__) || defined (NEED_EXTERN_PC)
extern
# endif /* __EMX__ || NEED_EXTERN_PC */
char PC, *BC, *UP;
#endif /* __linux__ */
#endif /* !__linux__ && !NCURSES_VERSION */
/* Some strings to control terminal actions. These are output by tputs (). */
char *_rl_term_clreol;
@ -350,9 +350,9 @@ rl_reset_screen_size ()
void
rl_resize_terminal ()
{
_rl_get_screen_size (fileno (rl_instream), 1);
if (_rl_echoing_p)
{
_rl_get_screen_size (fileno (rl_instream), 1);
if (CUSTOM_REDISPLAY_FUNC ())
rl_forced_update_display ();
else if (RL_ISSTATE(RL_STATE_REDISPLAYING) == 0)

View file

@ -1,6 +1,6 @@
/* text.c -- text handling commands for readline. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2010 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.
@ -150,7 +150,7 @@ rl_delete_text (from, to)
if (_rl_doing_an_undo == 0)
rl_add_undo (UNDO_DELETE, from, to, text);
else
free (text);
xfree (text);
rl_end -= diff;
rl_line_buffer[rl_end] = '\0';
@ -265,11 +265,13 @@ rl_forward_byte (count, key)
if (count > 0)
{
int end = rl_point + count;
int end, lend;
end = rl_point + count;
#if defined (VI_MODE)
int lend = rl_end > 0 ? rl_end - (VI_COMMAND_MODE()) : rl_end;
lend = rl_end > 0 ? rl_end - (VI_COMMAND_MODE()) : rl_end;
#else
int lend = rl_end;
lend = rl_end;
#endif
if (end > lend)
@ -287,6 +289,31 @@ rl_forward_byte (count, key)
return 0;
}
int
_rl_forward_char_internal (count)
int count;
{
int point;
#if defined (HANDLE_MULTIBYTE)
point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
#if defined (VI_MODE)
if (point >= rl_end && VI_COMMAND_MODE())
point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
#endif
if (rl_end < 0)
rl_end = 0;
#else
point = rl_point + count;
if (point > rl_end)
point = rl_end;
#endif
return (point);
}
#if defined (HANDLE_MULTIBYTE)
/* Move forward COUNT characters. */
int
@ -309,20 +336,12 @@ rl_forward_char (count, key)
return 0;
}
point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
#if defined (VI_MODE)
if (point >= rl_end && VI_COMMAND_MODE())
point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
#endif
point = _rl_forward_char_internal (count);
if (rl_point == point)
rl_ding ();
rl_point = point;
if (rl_end < 0)
rl_end = 0;
}
return 0;
@ -752,7 +771,7 @@ _rl_insert_char (count, c)
string[i] = '\0';
rl_insert_text (string);
free (string);
xfree (string);
return 0;
}
@ -779,7 +798,7 @@ _rl_insert_char (count, c)
count -= decreaser;
}
free (string);
xfree (string);
incoming_length = 0;
stored_count = 0;
#else /* !HANDLE_MULTIBYTE */
@ -805,8 +824,9 @@ _rl_insert_char (count, c)
/* We are inserting a single character.
If there is pending input, then make a string of all of the
pending characters that are bound to rl_insert, and insert
them all. */
if (_rl_any_typein ())
them all. Don't do this if we're current reading input from
a macro. */
if ((RL_ISSTATE (RL_STATE_MACROINPUT) == 0) && _rl_any_typein ())
_rl_insert_typein (c);
else
{
@ -1407,8 +1427,8 @@ rl_transpose_words (count, key)
/* I think that does it. */
rl_end_undo_group ();
free (word1);
free (word2);
xfree (word1);
xfree (word2);
return 0;
}
@ -1467,7 +1487,7 @@ rl_transpose_chars (count, key)
rl_end_undo_group ();
#if defined (HANDLE_MULTIBYTE)
free (dummy);
xfree (dummy);
#endif
return 0;
@ -1495,6 +1515,9 @@ _rl_char_search_internal (count, dir, schar)
int prepos;
#endif
if (dir == 0)
return -1;
pos = rl_point;
inc = (dir < 0) ? -1 : 1;
while (count)

View file

@ -378,7 +378,7 @@ tilde_expand_word (filename)
{
dirname = glue_prefix_and_suffix (expansion, filename, user_len);
xfree (username);
free (expansion);
xfree (expansion);
return (dirname);
}
}
@ -401,7 +401,7 @@ tilde_expand_word (filename)
if (expansion)
{
dirname = glue_prefix_and_suffix (expansion, filename, user_len);
free (expansion);
xfree (expansion);
}
}
/* If we don't have a failure hook, or if the failure hook did not

View file

@ -1,6 +1,6 @@
/* util.c -- readline utility functions */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2010 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.
@ -366,41 +366,56 @@ _rl_strpbrk (string1, string2)
#if !defined (HAVE_STRCASECMP)
/* Compare at most COUNT characters from string1 to string2. Case
doesn't matter. */
doesn't matter (strncasecmp). */
int
_rl_strnicmp (string1, string2, count)
char *string1, *string2;
int count;
{
register char ch1, ch2;
register char *s1, *s2;
int d;
while (count)
if (count <= 0 || (string1 == string2))
return 0;
s1 = string1;
s2 = string2;
do
{
ch1 = *string1++;
ch2 = *string2++;
if (_rl_to_upper(ch1) == _rl_to_upper(ch2))
count--;
else
d = _rl_to_lower (*s1) - _rl_to_lower (*s2); /* XXX - cast to unsigned char? */
if (d != 0)
return d;
if (*s1++ == '\0')
break;
s2++;
}
return (count);
while (--count != 0)
return (0);
}
/* strcmp (), but caseless. */
/* strcmp (), but caseless (strcasecmp). */
int
_rl_stricmp (string1, string2)
char *string1, *string2;
{
register char ch1, ch2;
register char *s1, *s2;
int d;
while (*string1 && *string2)
s1 = string1;
s2 = string2;
if (s1 == s2)
return 0;
while ((d = _rl_to_lower (*s1) - _rl_to_lower (*s2)) == 0)
{
ch1 = *string1++;
ch2 = *string2++;
if (_rl_to_upper(ch1) != _rl_to_upper(ch2))
return (1);
if (*s1++ == '\0')
return 0;
s2++;
}
return (*string1 - *string2);
return (d);
}
#endif /* !HAVE_STRCASECMP */

View file

@ -1,7 +1,7 @@
/* vi_mode.c -- A vi emulation mode for Bash.
Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2010 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.
@ -65,6 +65,8 @@
int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
_rl_vimotion_cxt *_rl_vimvcxt = 0;
/* Non-zero means enter insertion mode. */
static int _rl_vi_doing_insert;
@ -128,6 +130,16 @@ static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *));
static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
#endif
static int rl_domove_read_callback PARAMS((_rl_vimotion_cxt *));
static int rl_domove_motion_callback PARAMS((_rl_vimotion_cxt *));
static int rl_vi_domove_getchar PARAMS((_rl_vimotion_cxt *));
static int vi_change_dispatch PARAMS((_rl_vimotion_cxt *));
static int vi_delete_dispatch PARAMS((_rl_vimotion_cxt *));
static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *));
static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *));
void
_rl_vi_initialize_line ()
{
@ -618,12 +630,16 @@ _rl_vi_append_forward (key)
if (MB_CUR_MAX == 1 || rl_byte_oriented)
rl_point++;
else
{
point = rl_point;
rl_forward_char (1, key);
if (point == rl_point)
rl_point = rl_end;
}
{
point = rl_point;
#if 0
rl_forward_char (1, key);
#else
rl_point = _rl_forward_char_internal (1);
#endif
if (point == rl_point)
rl_point = rl_end;
}
}
}
@ -721,7 +737,7 @@ _rl_vi_done_inserting ()
_rl_vi_last_key_before_insert == 'a' ||
_rl_vi_last_key_before_insert == 'I' ||
_rl_vi_last_key_before_insert == 'A'))
_rl_vi_save_insert (rl_undo_list);
_rl_vi_save_insert (rl_undo_list);
/* XXX - Other keys probably need to be checked. */
else if (_rl_vi_last_key_before_insert == 'C')
rl_end_undo_group ();
@ -781,7 +797,7 @@ _rl_vi_change_mbchar_case (count)
if (MB_INVALIDCH (m))
wc = (wchar_t)rl_line_buffer[rl_point];
else if (MB_NULLWCH (m))
wc = L'\0';
wc = L'\0';
if (iswupper (wc))
wc = towlower (wc);
else if (iswlower (wc))
@ -809,7 +825,7 @@ _rl_vi_change_mbchar_case (count)
rl_vi_check ();
}
else
rl_forward_char (1, 0);
rl_forward_char (1, 0);
}
return 0;
@ -856,7 +872,7 @@ rl_vi_change_case (count, ignore)
_rl_insert_char (1, c);
rl_end_undo_group ();
rl_vi_check ();
}
}
else
rl_forward_char (1, c);
}
@ -894,7 +910,7 @@ rl_vi_check ()
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
else
rl_point--;
rl_point--;
}
return (0);
}
@ -910,113 +926,6 @@ rl_vi_column (count, key)
return (0);
}
int
rl_vi_domove (key, nextkey)
int key, *nextkey;
{
int c, save;
int old_end;
rl_mark = rl_point;
RL_SETSTATE(RL_STATE_MOREINPUT);
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
{
*nextkey = 0;
return -1;
}
*nextkey = c;
if (!member (c, vi_motion))
{
if (_rl_digit_p (c))
{
save = rl_numeric_arg;
rl_numeric_arg = _rl_digit_value (c);
rl_explicit_arg = 1;
RL_SETSTATE (RL_STATE_NUMERICARG|RL_STATE_VIMOTION);
rl_digit_loop1 ();
RL_UNSETSTATE (RL_STATE_VIMOTION);
rl_numeric_arg *= save;
RL_SETSTATE(RL_STATE_MOREINPUT);
c = rl_read_key (); /* real command */
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
{
*nextkey = 0;
return -1;
}
*nextkey = c;
}
else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
{
rl_mark = rl_end;
rl_beg_of_line (1, c);
_rl_vi_last_motion = c;
return (0);
}
else
return (-1);
}
_rl_vi_last_motion = c;
/* Append a blank character temporarily so that the motion routines
work right at the end of the line. */
old_end = rl_end;
rl_line_buffer[rl_end++] = ' ';
rl_line_buffer[rl_end] = '\0';
_rl_dispatch (c, _rl_keymap);
/* Remove the blank that we added. */
rl_end = old_end;
rl_line_buffer[rl_end] = '\0';
if (rl_point > rl_end)
rl_point = rl_end;
/* No change in position means the command failed. */
if (rl_mark == rl_point)
return (-1);
/* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
word. If we are not at the end of the line, and we are on a
non-whitespace character, move back one (presumably to whitespace). */
if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
!whitespace (rl_line_buffer[rl_point]))
rl_point--;
/* If cw or cW, back up to the end of a word, so the behaviour of ce
or cE is the actual result. Brute-force, no subtlety. */
if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
{
/* Don't move farther back than where we started. */
while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
rl_point--;
/* Posix.2 says that if cw or cW moves the cursor towards the end of
the line, the character under the cursor should be deleted. */
if (rl_point == rl_mark)
rl_point++;
else
{
/* Move past the end of the word so that the kill doesn't
remove the last letter of the previous word. Only do this
if we are not at the end of the line. */
if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
rl_point++;
}
}
if (rl_mark < rl_point)
SWAP (rl_point, rl_mark);
return (0);
}
/* Process C as part of the current numeric argument. Return -1 if the
argument should be aborted, 0 if we should not read any more chars, and
1 if we should continue to read chars. */
@ -1042,13 +951,13 @@ _rl_vi_arg_dispatch (c)
else
rl_numeric_arg = _rl_digit_value (c);
rl_explicit_arg = 1;
return 1;
return 1; /* keep going */
}
else
{
rl_clear_message ();
rl_stuff_char (key);
return 0;
return 0; /* done */
}
}
@ -1076,28 +985,233 @@ rl_digit_loop1 ()
return (0);
}
int
rl_vi_delete_to (count, key)
int count, key;
static void
_rl_mvcxt_init (m, op, key)
_rl_vimotion_cxt *m;
int op, key;
{
int c, start_pos;
m->op = op;
m->state = m->flags = 0;
m->ncxt = 0;
m->numeric_arg = -1;
m->start = rl_point;
m->end = rl_end;
m->key = key;
m->motion = -1;
}
if (_rl_uppercase_p (key))
rl_stuff_char ('$');
else if (vi_redoing)
rl_stuff_char (_rl_vi_last_motion);
static _rl_vimotion_cxt *
_rl_mvcxt_alloc (op, key)
int op, key;
{
_rl_vimotion_cxt *m;
start_pos = rl_point;
m = xmalloc (sizeof (_rl_vimotion_cxt));
_rl_mvcxt_init (m, op, key);
return m;
}
if (rl_vi_domove (key, &c))
static void
_rl_mvcxt_dispose (m)
_rl_vimotion_cxt *m;
{
xfree (m);
}
static int
rl_domove_motion_callback (m)
_rl_vimotion_cxt *m;
{
int c, save, r;
int old_end;
_rl_vi_last_motion = c = m->motion;
/* Append a blank character temporarily so that the motion routines
work right at the end of the line. */
old_end = rl_end;
rl_line_buffer[rl_end++] = ' ';
rl_line_buffer[rl_end] = '\0';
_rl_dispatch (c, _rl_keymap);
/* Remove the blank that we added. */
rl_end = old_end;
rl_line_buffer[rl_end] = '\0';
if (rl_point > rl_end)
rl_point = rl_end;
/* No change in position means the command failed. */
if (rl_mark == rl_point)
return (-1);
/* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
word. If we are not at the end of the line, and we are on a
non-whitespace character, move back one (presumably to whitespace). */
if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
!whitespace (rl_line_buffer[rl_point]))
rl_point--;
/* If cw or cW, back up to the end of a word, so the behaviour of ce
or cE is the actual result. Brute-force, no subtlety. */
if (m->key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
{
rl_ding ();
/* Don't move farther back than where we started. */
while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
rl_point--;
/* Posix.2 says that if cw or cW moves the cursor towards the end of
the line, the character under the cursor should be deleted. */
if (rl_point == rl_mark)
rl_point++;
else
{
/* Move past the end of the word so that the kill doesn't
remove the last letter of the previous word. Only do this
if we are not at the end of the line. */
if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
rl_point++;
}
}
if (rl_mark < rl_point)
SWAP (rl_point, rl_mark);
#if defined (READLINE_CALLBACKS)
if (RL_ISSTATE (RL_STATE_CALLBACK))
(*rl_redisplay_function)(); /* make sure motion is displayed */
#endif
r = vidomove_dispatch (m);
return (r);
}
#define RL_VIMOVENUMARG() (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG))
static int
rl_domove_read_callback (m)
_rl_vimotion_cxt *m;
{
int c, save;
c = m->motion;
if (member (c, vi_motion))
{
#if defined (READLINE_CALLBACKS)
/* If we just read a vi-mode motion command numeric argument, turn off
the `reading numeric arg' state */
if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
RL_UNSETSTATE (RL_STATE_NUMERICARG);
#endif
/* Should do everything, including turning off RL_STATE_VIMOTION */
return (rl_domove_motion_callback (m));
}
else if (m->key == c && (m->key == 'd' || m->key == 'y' || m->key == 'c'))
{
rl_mark = rl_end;
rl_beg_of_line (1, c);
_rl_vi_last_motion = c;
RL_UNSETSTATE (RL_STATE_VIMOTION);
return (0);
}
#if defined (READLINE_CALLBACKS)
/* XXX - these need to handle rl_universal_argument bindings */
/* Reading vi motion char continuing numeric argument */
else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
{
return (_rl_vi_arg_dispatch (c));
}
/* Readine vi motion char starting numeric argument */
else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_VIMOTION) && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
{
RL_SETSTATE (RL_STATE_NUMERICARG);
return (_rl_vi_arg_dispatch (c));
}
#endif
else if (_rl_digit_p (c))
{
/* This code path taken when not in callback mode */
save = rl_numeric_arg;
rl_numeric_arg = _rl_digit_value (c);
rl_explicit_arg = 1;
RL_SETSTATE (RL_STATE_NUMERICARG);
rl_digit_loop1 ();
rl_numeric_arg *= save;
c = rl_vi_domove_getchar (m);
if (c < 0)
{
m->motion = 0;
return -1;
}
m->motion = c;
return (rl_domove_motion_callback (m));
}
else
{
RL_UNSETSTATE (RL_STATE_VIMOTION);
RL_UNSETSTATE (RL_STATE_NUMERICARG);
return (1);
}
}
static int
rl_vi_domove_getchar (m)
_rl_vimotion_cxt *m;
{
int c;
RL_SETSTATE(RL_STATE_MOREINPUT);
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
return c;
}
#if defined (READLINE_CALLBACKS)
int
_rl_vi_domove_callback (m)
_rl_vimotion_cxt *m;
{
int c, r;
m->motion = c = rl_vi_domove_getchar (m);
/* XXX - what to do if this returns -1? Should we return 1 for eof to
callback code? */
r = rl_domove_read_callback (m);
return ((r == 0) ? r : 1); /* normalize return values */
}
#endif
/* This code path taken when not in callback mode. */
int
rl_vi_domove (x, ignore)
int x, *ignore;
{
int r;
_rl_vimotion_cxt *m;
m = _rl_vimvcxt;
*ignore = m->motion = rl_vi_domove_getchar (m);
if (m->motion < 0)
{
m->motion = 0;
return -1;
}
return (rl_domove_read_callback (m));
}
static int
vi_delete_dispatch (m)
_rl_vimotion_cxt *m;
{
/* These are the motion commands that do not require adjusting the
mark. */
if (((strchr (" l|h^0bBFT`", c) == 0) && (rl_point >= start_pos)) &&
if (((strchr (" l|h^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
(rl_mark < rl_end))
rl_mark++;
@ -1106,34 +1220,61 @@ rl_vi_delete_to (count, key)
}
int
rl_vi_change_to (count, key)
rl_vi_delete_to (count, key)
int count, key;
{
int c, start_pos;
int c, r;
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
_rl_vimvcxt->start = rl_point;
rl_mark = rl_point;
if (_rl_uppercase_p (key))
rl_stuff_char ('$');
{
_rl_vimvcxt->motion = '$';
r = rl_domove_motion_callback (_rl_vimvcxt);
}
else if (vi_redoing)
rl_stuff_char (_rl_vi_last_motion);
{
_rl_vimvcxt->motion = _rl_vi_last_motion;
r = rl_domove_motion_callback (_rl_vimvcxt);
}
#if defined (READLINE_CALLBACKS)
else if (RL_ISSTATE (RL_STATE_CALLBACK))
{
RL_SETSTATE (RL_STATE_VIMOTION);
return (0);
}
#endif
else
r = rl_vi_domove (key, &c);
start_pos = rl_point;
if (rl_vi_domove (key, &c))
if (r < 0)
{
rl_ding ();
return -1;
r = -1;
}
_rl_mvcxt_dispose (_rl_vimvcxt);
_rl_vimvcxt = 0;
return r;
}
static int
vi_change_dispatch (m)
_rl_vimotion_cxt *m;
{
/* These are the motion commands that do not require adjusting the
mark. c[wW] are handled by special-case code in rl_vi_domove(),
and already leave the mark at the correct location. */
if (((strchr (" l|hwW^0bBFT`", c) == 0) && (rl_point >= start_pos)) &&
if (((strchr (" l|hwW^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
(rl_mark < rl_end))
rl_mark++;
/* The cursor never moves with c[wW]. */
if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
rl_point = start_pos;
if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start)
rl_point = m->start;
if (vi_redoing)
{
@ -1151,44 +1292,138 @@ rl_vi_change_to (count, key)
rl_begin_undo_group (); /* to make the `u' command work */
rl_kill_text (rl_point, rl_mark);
/* `C' does not save the text inserted for undoing or redoing. */
if (_rl_uppercase_p (key) == 0)
_rl_vi_doing_insert = 1;
rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign);
if (_rl_uppercase_p (m->key) == 0)
_rl_vi_doing_insert = 1;
/* XXX -- TODO -- use m->numericarg? */
rl_vi_start_inserting (m->key, rl_numeric_arg, rl_arg_sign);
}
return (0);
}
int
rl_vi_change_to (count, key)
int count, key;
{
int c, r;
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
_rl_vimvcxt->start = rl_point;
rl_mark = rl_point;
if (_rl_uppercase_p (key))
{
_rl_vimvcxt->motion = '$';
r = rl_domove_motion_callback (_rl_vimvcxt);
}
else if (vi_redoing)
{
_rl_vimvcxt->motion = _rl_vi_last_motion;
r = rl_domove_motion_callback (_rl_vimvcxt);
}
#if defined (READLINE_CALLBACKS)
else if (RL_ISSTATE (RL_STATE_CALLBACK))
{
RL_SETSTATE (RL_STATE_VIMOTION);
return (0);
}
#endif
else
r = rl_vi_domove (key, &c);
if (r < 0)
{
rl_ding ();
r = -1; /* normalize return value */
}
_rl_mvcxt_dispose (_rl_vimvcxt);
_rl_vimvcxt = 0;
return r;
}
static int
vi_yank_dispatch (m)
_rl_vimotion_cxt *m;
{
/* These are the motion commands that do not require adjusting the
mark. */
if (((strchr (" l|h^0%bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
(rl_mark < rl_end))
rl_mark++;
rl_begin_undo_group ();
rl_kill_text (rl_point, rl_mark);
rl_end_undo_group ();
rl_do_undo ();
rl_point = m->start;
return (0);
}
int
rl_vi_yank_to (count, key)
int count, key;
{
int c, start_pos;
int c, r;
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
_rl_vimvcxt->start = rl_point;
rl_mark = rl_point;
if (_rl_uppercase_p (key))
rl_stuff_char ('$');
{
_rl_vimvcxt->motion = '$';
r = rl_domove_motion_callback (_rl_vimvcxt);
}
#if defined (READLINE_CALLBACKS)
else if (RL_ISSTATE (RL_STATE_CALLBACK))
{
RL_SETSTATE (RL_STATE_VIMOTION);
return (0);
}
#endif
else
r = rl_vi_domove (key, &c);
start_pos = rl_point;
if (rl_vi_domove (key, &c))
if (r < 0)
{
rl_ding ();
return -1;
r = -1;
}
/* These are the motion commands that do not require adjusting the
mark. */
if (((strchr (" l|h^0%bBFT`", c) == 0) && (rl_point >= start_pos)) &&
(rl_mark < rl_end))
rl_mark++;
_rl_mvcxt_dispose (_rl_vimvcxt);
_rl_vimvcxt = 0;
rl_begin_undo_group ();
rl_kill_text (rl_point, rl_mark);
rl_end_undo_group ();
rl_do_undo ();
rl_point = start_pos;
return r;
}
return (0);
static int
vidomove_dispatch (m)
_rl_vimotion_cxt *m;
{
int r;
switch (m->op)
{
case VIM_DELETE:
r = vi_delete_dispatch (m);
break;
case VIM_CHANGE:
r = vi_change_dispatch (m);
break;
case VIM_YANK:
r = vi_yank_dispatch (m);
break;
default:
_rl_errmsg ("vidomove_dispatch: unknown operator %d", m->op);
r = 1;
break;
}
RL_UNSETSTATE (RL_STATE_VIMOTION);
return r;
}
int
@ -1317,27 +1552,38 @@ rl_vi_char_search (count, key)
#endif
if (key == ';' || key == ',')
_rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
{
if (_rl_cs_orig_dir == 0)
return -1;
#if defined (HANDLE_MULTIBYTE)
if (_rl_vi_last_search_mblen == 0)
return -1;
#else
if (_rl_vi_last_search_char == 0)
return -1;
#endif
_rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
}
else
{
switch (key)
{
case 't':
_rl_cs_orig_dir = _rl_cs_dir = FTO;
break;
{
case 't':
_rl_cs_orig_dir = _rl_cs_dir = FTO;
break;
case 'T':
_rl_cs_orig_dir = _rl_cs_dir = BTO;
break;
case 'T':
_rl_cs_orig_dir = _rl_cs_dir = BTO;
break;
case 'f':
_rl_cs_orig_dir = _rl_cs_dir = FFIND;
break;
case 'f':
_rl_cs_orig_dir = _rl_cs_dir = FFIND;
break;
case 'F':
_rl_cs_orig_dir = _rl_cs_dir = BFIND;
break;
}
case 'F':
_rl_cs_orig_dir = _rl_cs_dir = BFIND;
break;
}
if (vi_redoing)
{
@ -1345,12 +1591,12 @@ rl_vi_char_search (count, key)
}
#if defined (READLINE_CALLBACKS)
else if (RL_ISSTATE (RL_STATE_CALLBACK))
{
_rl_callback_data = _rl_callback_data_alloc (count);
_rl_callback_data->i1 = _rl_cs_dir;
_rl_callback_func = _rl_vi_callback_char_search;
return (0);
}
{
_rl_callback_data = _rl_callback_data_alloc (count);
_rl_callback_data->i1 = _rl_cs_dir;
_rl_callback_func = _rl_vi_callback_char_search;
return (0);
}
#endif
else
{
@ -1401,7 +1647,7 @@ rl_vi_match (ignore, key)
pre = rl_point;
rl_forward_char (1, key);
if (pre == rl_point)
break;
break;
}
}
else
@ -1430,7 +1676,7 @@ rl_vi_match (ignore, key)
{
pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
if (tmp == pos)
pos--;
pos--;
}
if (pos >= 0)
{
@ -1678,8 +1924,8 @@ rl_vi_replace (count, key)
vi_replace_map[NEWLINE].function = rl_newline;
/* If the normal vi insertion keymap has ^H bound to erase, do the
same here. Probably should remove the assignment to RUBOUT up
there, but I don't think it will make a difference in real life. */
same here. Probably should remove the assignment to RUBOUT up
there, but I don't think it will make a difference in real life. */
if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;

50
lib/readline/xfree.c Normal file
View file

@ -0,0 +1,50 @@
/* xfree.c -- safe version of free that ignores attempts to free NUL */
/* Copyright (C) 1991-2010 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
#if defined (HAVE_STDLIB_H)
# include <stdlib.h>
#else
# include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */
#include "xmalloc.h"
/* **************************************************************** */
/* */
/* Memory Deallocation. */
/* */
/* **************************************************************** */
/* Use this as the function to call when adding unwind protects so we
don't need to know what free() returns. */
void
xfree (string)
PTR_T string;
{
if (string)
free (string);
}

View file

@ -77,13 +77,3 @@ xrealloc (pointer, bytes)
memory_error_and_abort ("xrealloc");
return (temp);
}
/* Use this as the function to call when adding unwind protects so we
don't need to know what free() returns. */
void
xfree (string)
PTR_T string;
{
if (string)
free (string);
}

View file

@ -2,7 +2,7 @@
# Makefile for the Bash library
#
#
# Copyright (C) 1998-2009 Free Software Foundation, Inc.
# Copyright (C) 1998-2010 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -91,7 +91,8 @@ 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 mbscasecmp.c fnxform.c
casemod.c dprintf.c input_avail.c mbscasecmp.c fnxform.c \
strchrnul.c unicode.c wcswidth.c shmbchar.c
# The header files for this library.
HSOURCES =
@ -105,7 +106,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 mbscasecmp.o fnxform.o ${LIBOBJS}
input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o ${LIBOBJS}
SUPPORT = Makefile
@ -144,7 +145,7 @@ casemod.o: casemod.c
clktck.o: clktck.c
clock.o: clock.c
eaccess.o: eaccess.c
fdprintf.o: fdprintf.c
dprintf.o: dprintf.c
fmtullong.o: fmtullong.c
fmtulong.o: fmtulong.c
fmtumax.o: fmtumax.c
@ -168,6 +169,7 @@ pathcanon.o: pathcanon.c
pathphys.o: pathphys.c
rename.o: rename.c
setlinebuf.o: setlinebuf.c
shmbchar.o: shmbchar.c
shquote.o: shquote.c
shtty.o: shtty.c
snprintf.o: snprintf.c
@ -195,6 +197,7 @@ uconvert.o: uconvert.c
ufuncs.o: ufuncs.c
vprint.o: vprint.c
wcsdup.o: wcsdup.c
wcswidth.o: wcswidth.c
mbschr.o: mbschr.c
zcatfd.o: zcatfd.c
zmapfd.o: zmapfd.c
@ -214,7 +217,7 @@ casemod.o: ${BUILD_DIR}/config.h
clktck.o: ${BUILD_DIR}/config.h
clock.o: ${BUILD_DIR}/config.h
eaccess.o: ${BUILD_DIR}/config.h
fdprintf.o: ${BUILD_DIR}/config.h
dprintf.o: ${BUILD_DIR}/config.h
fmtullong.o: ${BUILD_DIR}/config.h
fmtulong.o: ${BUILD_DIR}/config.h
fmtumax.o: ${BUILD_DIR}/config.h
@ -238,6 +241,7 @@ pathcanon.o: ${BUILD_DIR}/config.h
pathphys.o: ${BUILD_DIR}/config.h
rename.o: ${BUILD_DIR}/config.h
setlinebuf.o: ${BUILD_DIR}/config.h
shmbchare.o: ${BUILD_DIR}/config.h
shquote.o: ${BUILD_DIR}/config.h
shtty.o: ${BUILD_DIR}/config.h
snprintf.o: ${BUILD_DIR}/config.h
@ -265,6 +269,7 @@ uconvert.o: ${BUILD_DIR}/config.h
ufuncs.o: ${BUILD_DIR}/config.h
vprint.o: ${BUILD_DIR}/config.h
wcsdup.o: ${BUILD_DIR}/config.h
wcswidth.o: ${BUILD_DIR}/config.h
mbschr.o: ${BUILD_DIR}/config.h
zcatfd.o: ${BUILD_DIR}/config.h
zgetline.o: ${BUILD_DIR}/config.h
@ -505,9 +510,12 @@ wcsdup.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcsdup.o: ${BASHINCDIR}/stdc.h
wcsdup.o: ${topdir}/xmalloc.h
wcswidth.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcswidth.o: ${BASHINCDIR}/stdc.h
mbschr.o: ${topdir}/bashansi.h
mbschr.o: ${BASHINCDIR}/ansi_stdlib.h
mbschr.o: ${BASHINCDIR}/shmbutil.h
mbschr.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
zgetline.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
zgetline.o: ${BASHINCDIR}/stdc.h
@ -526,10 +534,10 @@ casemod.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
casemod.o: ${BASHINCDIR}/stdc.h
casemod.o: ${topdir}/xmalloc.h
casemod.o: ${topdir}/bashtypes.h
casemod.o: ${BASHINCDIR}/shmbutil.h
casemod.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
casemod.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
fdprintf.o: ${BASHINCDIR}/stdc.h
dprintf.o: ${BASHINCDIR}/stdc.h
input_avail.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
input_avail.o: ${BASHINCDIR}/stdc.h
@ -542,3 +550,5 @@ fnxform.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
fnxform.o: ${BASHINCDIR}/stdc.h
fnxform.o: ${topdir}/bashtypes.h
fnxform.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
shmbchar.o: ${BASHINCDIR}/shmbchar.h

View file

@ -111,6 +111,13 @@ sh_modcase (string, pat, flags)
mbstate_t state;
#endif
if (string == 0 || *string == 0)
{
ret = (char *)xmalloc (1);
ret[0] = '\0';
return ret;
}
#if defined (HANDLE_MULTIBYTE)
memset (&state, 0, sizeof (mbstate_t));
#endif

70
lib/sh/dprintf.c Normal file
View file

@ -0,0 +1,70 @@
/* dprintf -- printf to a file descriptor */
/* Copyright (C) 2008-2010 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/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdc.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (PREFER_STDARG)
# include <stdarg.h>
#else
# include <varargs.h>
#endif
#include <stdio.h>
int
#if defined (PREFER_STDARG)
dprintf(int fd, const char *format, ...)
#else
dprintf(fd, format, va_alist)
int fd;
const char *format;
va_dcl
#endif
{
FILE *fp;
int fd2, rc, r2;
va_list args;
if ((fd2 = dup(fd)) < 0)
return -1;
fp = fdopen (fd2, "w");
if (fp == 0)
{
close (fd2);
return -1;
}
SH_VA_START (args, format);
rc = vfprintf (fp, format, args);
fflush (fp);
va_end (args);
r2 = fclose (fp); /* check here */
return rc;
}

View file

@ -1,6 +1,6 @@
/* eaccess.c - eaccess replacement for the shell, plus other access functions. */
/* Copyright (C) 2006 Free Software Foundation, Inc.
/* Copyright (C) 2006-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -198,11 +198,20 @@ sh_eaccess (path, mode)
char *path;
int mode;
{
int ret;
if (path_is_devfd (path))
return (sh_stataccess (path, mode));
#if defined (HAVE_EACCESS) /* FreeBSD */
return (eaccess (path, mode));
#if defined (HAVE_FACCESSAT) && defined (AT_EACCESS)
return (faccessat (AT_FDCWD, path, mode, AT_EACCESS));
#elif defined (HAVE_EACCESS) /* FreeBSD */
ret = eaccess (path, mode); /* XXX -- not always correct for X_OK */
# if defined (__FreeBSD__)
if (ret == 0 && current_user.euid == 0 && mode == X_OK)
return (sh_stataccess (path, mode));
# endif
return ret;
#elif defined (EFF_ONLY_OK) /* SVR4(?), SVR4.2 */
return access (path, mode|EFF_ONLY_OK);
#else
@ -215,7 +224,15 @@ sh_eaccess (path, mode)
# endif
if (current_user.uid == current_user.euid && current_user.gid == current_user.egid)
return (access (path, mode));
{
ret = access (path, mode);
#if defined (__FreeBSD__) || defined (SOLARIS)
if (ret == 0 && current_user.euid == 0 && mode == X_OK)
return (sh_stataccess (path, mode));
#endif
return ret;
}
return (sh_stataccess (path, mode));
#endif

199
lib/sh/fnxform.c Normal file
View file

@ -0,0 +1,199 @@
/* fnxform - use iconv(3) to transform strings to and from "filename" format */
/* Copyright (C) 2009-2010 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/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "bashansi.h"
#include <stdio.h>
#include "bashtypes.h"
#include "stdc.h"
#include "bashintl.h"
#include <xmalloc.h>
#if defined (HAVE_ICONV)
# include <iconv.h>
#endif
#if defined (HAVE_LOCALE_CHARSET)
extern const char *locale_charset __P((void));
#else
extern char *get_locale_var __P((char *));
#endif
#if defined (HAVE_ICONV)
static iconv_t conv_fromfs = (iconv_t)-1;
static iconv_t conv_tofs = (iconv_t)-1;
#define OUTLEN_MAX 4096
static char *outbuf = 0;
static size_t outlen = 0;
static char *curencoding __P((void));
static void init_tofs __P((void));
static void init_fromfs __P((void));
static char *
curencoding ()
{
char *loc;
#if defined (HAVE_LOCALE_CHARSET)
loc = (char *)locale_charset ();
return loc;
#else
char *dot, *mod;
loc = get_locale_var ("LC_CTYPE");
if (loc == 0 || *loc == 0)
return "";
dot = strchr (loc, '.');
if (dot == 0)
return loc;
mod = strchr (dot, '@');
if (mod)
*mod = '\0';
return ++dot;
#endif
}
static void
init_tofs ()
{
char *cur;
cur = curencoding ();
conv_tofs = iconv_open ("UTF-8-MAC", cur);
}
static void
init_fromfs ()
{
char *cur;
cur = curencoding ();
conv_fromfs = iconv_open (cur, "UTF-8-MAC");
}
char *
fnx_tofs (string, len)
char *string;
size_t len;
{
#ifdef MACOSX
ICONV_CONST char *inbuf;
char *tempbuf;
size_t templen;
if (conv_tofs == (iconv_t)-1)
init_tofs ();
if (conv_tofs == (iconv_t)-1)
return string;
/* Free and reallocate outbuf if it's *too* big */
if (outlen >= OUTLEN_MAX && len < OUTLEN_MAX - 8)
{
free (outbuf);
outbuf = 0;
outlen = 0;
}
inbuf = string;
if (outbuf == 0 || outlen < len + 8)
{
outlen = len + 8;
outbuf = outbuf ? xrealloc (outbuf, outlen + 1) : xmalloc (outlen + 1);
}
tempbuf = outbuf;
templen = outlen;
iconv (conv_tofs, NULL, NULL, NULL, NULL);
if (iconv (conv_tofs, &inbuf, &len, &tempbuf, &templen) == (size_t)-1)
return string;
*tempbuf = '\0';
return outbuf;
#else
return string;
#endif
}
char *
fnx_fromfs (string, len)
char *string;
size_t len;
{
#ifdef MACOSX
ICONV_CONST char *inbuf;
char *tempbuf;
size_t templen;
if (conv_fromfs == (iconv_t)-1)
init_fromfs ();
if (conv_fromfs == (iconv_t)-1)
return string;
/* Free and reallocate outbuf if it's *too* big */
if (outlen >= OUTLEN_MAX && len < OUTLEN_MAX - 8)
{
free (outbuf);
outbuf = 0;
outlen = 0;
}
inbuf = string;
if (outbuf == 0 || outlen < (len + 8))
{
outlen = len + 8;
outbuf = outbuf ? xrealloc (outbuf, outlen + 1) : xmalloc (outlen + 1);
}
tempbuf = outbuf;
templen = outlen;
iconv (conv_fromfs, NULL, NULL, NULL, NULL);
if (iconv (conv_fromfs, &inbuf, &len, &tempbuf, &templen) == (size_t)-1)
return string;
*tempbuf = '\0';
return outbuf;
#else
return string;
#endif
}
#else
char *
fnx_tofs (string)
char *string;
{
return string;
}
char *
fnx_fromfs (string)
char *string;
{
return string;
}
#endif

View file

@ -1,6 +1,6 @@
/* fpurge - Flushing buffers of a FILE stream. */
/* Copyright (C) 2007 Free Software Foundation, Inc.
/* Copyright (C) 2007-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -36,6 +36,90 @@ extern int fpurge __P((FILE *stream));
#endif
#include <stdlib.h>
/* Inline contents of gnulib:stdio-impl.h */
/* Many stdio implementations have the same logic and therefore can share
the same implementation of stdio extension API, except that some fields
have different naming conventions, or their access requires some casts. */
/* BSD stdio derived implementations. */
#if defined __NetBSD__ /* NetBSD */
/* Get __NetBSD_Version__. */
# include <sys/param.h>
#endif
#if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
# if defined __DragonFly__ /* DragonFly */
/* See <http://www.dragonflybsd.org/cvsweb/src/lib/libc/stdio/priv_stdio.h?rev=HEAD&content-type=text/x-cvsweb-markup>. */
# define fp_ ((struct { struct __FILE_public pub; \
struct { unsigned char *_base; int _size; } _bf; \
void *cookie; \
void *_close; \
void *_read; \
void *_seek; \
void *_write; \
struct { unsigned char *_base; int _size; } _ub; \
int _ur; \
unsigned char _ubuf[3]; \
unsigned char _nbuf[1]; \
struct { unsigned char *_base; int _size; } _lb; \
int _blksize; \
fpos_t _offset; \
/* More fields, not relevant here. */ \
} *) fp)
/* See <http://www.dragonflybsd.org/cvsweb/src/include/stdio.h?rev=HEAD&content-type=text/x-cvsweb-markup>. */
# define _p pub._p
# define _flags pub._flags
# define _r pub._r
# define _w pub._w
# else
# define fp_ fp
# endif
# if (defined __NetBSD__ && __NetBSD_Version__ >= 105270000) || defined __OpenBSD__ /* NetBSD >= 1.5ZA, OpenBSD */
/* See <http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
and <http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup> */
struct __sfileext
{
struct __sbuf _ub; /* ungetc buffer */
/* More fields, not relevant here. */
};
# define fp_ub ((struct __sfileext *) fp->_ext._base)->_ub
# else /* FreeBSD, NetBSD <= 1.5Z, DragonFly, MacOS X, Cygwin */
# define fp_ub fp_->_ub
# endif
# define HASUB(fp) (fp_ub._base != NULL)
#endif
/* SystemV derived implementations. */
#if defined _IOERR
# if defined __sun && defined _LP64 /* Solaris/{SPARC,AMD64} 64-bit */
# define fp_ ((struct { unsigned char *_ptr; \
unsigned char *_base; \
unsigned char *_end; \
long _cnt; \
int _file; \
unsigned int _flag; \
} *) fp)
# else
# define fp_ fp
# endif
# if defined _SCO_DS /* OpenServer */
# define _cnt __cnt
# define _ptr __ptr
# define _base __base
# define _flag __flag
# endif
#endif
int
fpurge (FILE *fp)
{
@ -45,7 +129,7 @@ fpurge (FILE *fp)
/* The __fpurge function does not have a return value. */
return 0;
#elif HAVE_FPURGE /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X */
#elif HAVE_FPURGE /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin 1.7 */
/* Call the system's fpurge function. */
# undef fpurge
@ -59,10 +143,10 @@ fpurge (FILE *fp)
<stdio.h> on BSD systems says:
"The following always hold: if _flags & __SRD, _w is 0."
If this invariant is not fulfilled and the stream is read-write but
currently writing, subsequent putc or fputc calls will write directly
currently reading, subsequent putc or fputc calls will write directly
into the buffer, although they shouldn't be allowed to. */
if ((fp->_flags & __SRD) != 0)
fp->_w = 0;
if ((fp_->_flags & __SRD) != 0)
fp_->_w = 0;
# endif
return result;
@ -101,7 +185,7 @@ fpurge (FILE *fp)
fp->_wcount = 0;
fp->_ungetc_count = 0;
return 0;
# elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw */
# elif defined _IOERR || defined __TANDEM /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw */
fp->_ptr = fp->_base;
if (fp->_ptr != NULL)
fp->_cnt = 0;

78
lib/sh/mbscasecmp.c Normal file
View file

@ -0,0 +1,78 @@
/* mbscasecmp - case-insensitive multibyte string comparison. */
/* Copyright (C) 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/>.
*/
#include <config.h>
#if !defined (HAVE_MBSCASECMP) && defined (HANDLE_MULTIBYTE)
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <wchar.h>
#include <wctype.h>
/* Compare MBS1 and MBS2 without regard to case. */
int
mbscasecmp (mbs1, mbs2)
const char *mbs1;
const char *mbs2;
{
int len1, len2;
wchar_t c1, c2, l1, l2;
len1 = len2 = 0;
/* Reset multibyte characters to their initial state. */
(void) mblen ((char *) NULL, 0);
do
{
len1 = mbtowc (&c1, mbs1, MB_CUR_MAX);
len2 = mbtowc (&c2, mbs2, MB_CUR_MAX);
if (len1 == 0)
return len2 == 0 ? 0 : -1;
else if (len2 == 0)
return 1;
else if (len1 > 0 && len2 < 0)
return -1;
else if (len1 < 0 && len2 > 0)
return 1;
else if (len1 < 0 && len2 < 0)
{
len1 = strlen (mbs1);
len2 = strlen (mbs2);
return (len1 == len2 ? memcmp (mbs1, mbs2, len1)
: ((len1 < len2) ? (memcmp (mbs1, mbs2, len1) > 0 ? 1 : -1)
: (memcmp (mbs1, mbs2, len2) >= 0 ? 1 : -1)));
}
l1 = towlower (c1);
l2 = towlower (c2);
mbs1 += len1;
mbs2 += len2;
}
while (l1 == l2);
return l1 - l2;
}
#endif

78
lib/sh/mbschr.c Normal file
View file

@ -0,0 +1,78 @@
/* mbschr.c - strchr(3) that handles multibyte characters. */
/* Copyright (C) 2002 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/>.
*/
#include <config.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include "bashansi.h"
#include "shmbutil.h"
#undef mbschr
/* In some locales, the non-first byte of some multibyte characters have
the same value as some ascii character. Faced with these strings, a
legacy strchr() might return the wrong value. */
char *
#if defined (PROTOTYPES)
mbschr (const char *s, int c)
#else
mbschr (s, c)
const char *s;
int c;
#endif
{
#if HANDLE_MULTIBYTE
char *pos;
mbstate_t state;
size_t strlength, mblength;
/* The locale encodings with said weird property are BIG5, BIG5-HKSCS,
GBK, GB18030, SHIFT_JIS, and JOHAB. They exhibit the problem only
when c >= 0x30. We can therefore use the faster bytewise search if
c <= 0x30. */
if ((unsigned char)c >= '0' && MB_CUR_MAX > 1)
{
pos = (char *)s;
memset (&state, '\0', sizeof(mbstate_t));
strlength = strlen (s);
while (strlength > 0)
{
mblength = mbrlen (pos, strlength, &state);
if (mblength == (size_t)-2 || mblength == (size_t)-1 || mblength == (size_t)0)
mblength = 1;
if (mblength == 1 && c == (unsigned char)*pos)
return pos;
strlength -= mblength;
pos += mblength;
}
return ((char *)NULL);
}
else
#endif
return (strchr (s, c));
}

View file

@ -1,6 +1,6 @@
/* oslib.c - functions present only in some unix versions. */
/* Copyright (C) 1995 Free Software Foundation, Inc.
/* Copyright (C) 1995,2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -37,6 +37,10 @@
#include <filecntl.h>
#include <bashansi.h>
#if !defined (HAVE_KILLPG)
# include <signal.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <chartypes.h>
@ -209,7 +213,8 @@ gethostname (name, namelen)
# else /* !HAVE_UNAME */
int
gethostname (name, namelen)
int name, namelen;
char *name;
int namelen;
{
strncpy (name, "unknown", namelen);
name[namelen] = '\0';

View file

@ -62,7 +62,7 @@ sh_regmatch (string, pattern, flags)
#if defined (ARRAY_VARS)
rematch = (SHELL_VAR *)NULL;
#endif
rflags = REG_EXTENDED;
if (glob_ignore_case || match_ignore_case)
rflags |= REG_ICASE;

92
lib/sh/shmbchar.c Normal file
View file

@ -0,0 +1,92 @@
/* Copyright (C) 2001, 2006, 2009, 2010 Free Software Foundation, Inc.
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#if defined (HANDLE_MULTIBYTE)
#include <stdlib.h>
#include <limits.h>
#include <shmbutil.h>
#include <shmbchar.h>
#if IS_BASIC_ASCII
/* Bit table of characters in the ISO C "basic character set". */
const unsigned int is_basic_table [UCHAR_MAX / 32 + 1] =
{
0x00001a00, /* '\t' '\v' '\f' */
0xffffffef, /* ' '...'#' '%'...'?' */
0xfffffffe, /* 'A'...'Z' '[' '\\' ']' '^' '_' */
0x7ffffffe /* 'a'...'z' '{' '|' '}' '~' */
/* The remaining bits are 0. */
};
#endif /* IS_BASIC_ASCII */
size_t
mbstrlen (s)
const char *s;
{
size_t clen, nc;
mbstate_t mbs = { 0 }, mbsbak = { 0 };
int f;
nc = 0;
while (*s && (clen = (f = is_basic (*s)) ? 1 : mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
{
if (MB_INVALIDCH(clen))
{
clen = 1; /* assume single byte */
mbs = mbsbak;
}
if (f == 0)
mbsbak = mbs;
s += clen;
nc++;
}
return nc;
}
/* Return pointer to first multibyte char in S, or NULL if none. */
char *
mbsmbchar (s)
const char *s;
{
char *t;
size_t clen;
mbstate_t mbs = { 0 };
for (t = (char *)s; *t; t++)
{
if (is_basic (*t))
continue;
clen = mbrlen (t, MB_CUR_MAX, &mbs);
if (clen == 0)
return 0;
if (MB_INVALIDCH(clen))
continue;
if (clen > 1)
return t;
}
return 0;
}
#endif

View file

@ -42,10 +42,11 @@
Used by alias and trap, among others. */
char *
sh_single_quote (string)
char *string;
const char *string;
{
register int c;
char *result, *r, *s;
char *result, *r;
const char *s;
result = (char *)xmalloc (3 + (4 * strlen (string)));
r = result;
@ -72,10 +73,11 @@ sh_single_quote (string)
/* Quote STRING using double quotes. Return a new string. */
char *
sh_double_quote (string)
char *string;
const char *string;
{
register unsigned char c;
char *result, *r, *s;
char *result, *r;
const char *s;
result = (char *)xmalloc (3 + (2 * strlen (string)));
r = result;

View file

@ -9,7 +9,7 @@
Unix snprintf implementation.
derived from inetutils/libinetutils/snprintf.c Version 1.1
Copyright (C) 2001,2006 Free Software Foundation, Inc.
Copyright (C) 2001,2006,2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.

46
lib/sh/strcasestr.c Normal file
View file

@ -0,0 +1,46 @@
/* strcasestr.c - Find if one string appears as a substring of another string,
without regard to case. */
/* Copyright (C) 2000 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/>.
*/
#include <config.h>
#include <bashansi.h>
#include <chartypes.h>
#include <stdc.h>
/* Determine if s2 occurs in s1. If so, return a pointer to the
match in s1. The compare is case insensitive. This is a
case-insensitive strstr(3). */
char *
strcasestr (s1, s2)
const char *s1;
const char *s2;
{
register int i, l, len, c;
c = TOLOWER ((unsigned char)s2[0]);
len = strlen (s1);
l = strlen (s2);
for (i = 0; (len - i) >= l; i++)
if ((TOLOWER ((unsigned char)s1[i]) == c) && (strncasecmp (s1 + i, s2, l) == 0))
return ((char *)s1 + i);
return ((char *)0);
}

144
lib/sh/strchrnul.c Normal file
View file

@ -0,0 +1,144 @@
/* Searching in a string.
Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <string.h>
/* On 32-bit hardware, choosing longword to be a 32-bit unsigned
long instead of a 64-bit uintmax_t tends to give better
performance. On 64-bit hardware, unsigned long is generally 64
bits already. Change this typedef to experiment with
performance. */
typedef unsigned long int longword;
/* Find the first occurrence of C in S or the final NUL byte. */
char *
strchrnul (s, c_in)
const char *s;
int c_in;
{
const unsigned char *char_ptr;
const longword *longword_ptr;
longword repeated_one;
longword repeated_c;
unsigned char c;
c = (unsigned char) c_in;
if (c == 0) /* find final null byte */
return (char *)(s ? (s + strlen (s)) : s);
/* Handle the first few bytes by reading one byte at a time.
Do this until CHAR_PTR is aligned on a longword boundary. */
for (char_ptr = (const unsigned char *) s;
(size_t) char_ptr % sizeof (longword) != 0;
++char_ptr)
if (!*char_ptr || *char_ptr == c)
return (char *) char_ptr;
longword_ptr = (const longword *) char_ptr;
/* All these elucidatory comments refer to 4-byte longwords,
but the theory applies equally well to any size longwords. */
/* Compute auxiliary longword values:
repeated_one is a value which has a 1 in every byte.
repeated_c has c in every byte. */
repeated_one = 0x01010101;
repeated_c = c | (c << 8);
repeated_c |= repeated_c << 16;
if (0xffffffffU < (longword) -1)
{
repeated_one |= repeated_one << 31 << 1;
repeated_c |= repeated_c << 31 << 1;
if (8 < sizeof (longword))
{
size_t i;
for (i = 64; i < sizeof (longword) * 8; i *= 2)
{
repeated_one |= repeated_one << i;
repeated_c |= repeated_c << i;
}
}
}
/* Instead of the traditional loop which tests each byte, we will
test a longword at a time. The tricky part is testing if *any of
the four* bytes in the longword in question are equal to NUL or
c. We first use an xor with repeated_c. This reduces the task
to testing whether *any of the four* bytes in longword1 or
longword2 is zero.
Let's consider longword1. We compute tmp =
((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
That is, we perform the following operations:
1. Subtract repeated_one.
2. & ~longword1.
3. & a mask consisting of 0x80 in every byte.
Consider what happens in each byte:
- If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
and step 3 transforms it into 0x80. A carry can also be propagated
to more significant bytes.
- If a byte of longword1 is nonzero, let its lowest 1 bit be at
position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
the byte ends in a single bit of value 0 and k bits of value 1.
After step 2, the result is just k bits of value 1: 2^k - 1. After
step 3, the result is 0. And no carry is produced.
So, if longword1 has only non-zero bytes, tmp is zero.
Whereas if longword1 has a zero byte, call j the position of the least
significant zero byte. Then the result has a zero at positions 0, ...,
j-1 and a 0x80 at position j. We cannot predict the result at the more
significant bytes (positions j+1..3), but it does not matter since we
already have a non-zero bit at position 8*j+7.
The test whether any byte in longword1 or longword2 is zero is equivalent
to testing whether tmp1 is nonzero or tmp2 is nonzero. We can combine
this into a single test, whether (tmp1 | tmp2) is nonzero.
This test can read more than one byte beyond the end of a string,
depending on where the terminating NUL is encountered. However,
this is considered safe since the initialization phase ensured
that the read will be aligned, therefore, the read will not cross
page boundaries and will not cause a fault. */
while (1)
{
longword longword1 = *longword_ptr ^ repeated_c;
longword longword2 = *longword_ptr;
if (((((longword1 - repeated_one) & ~longword1)
| ((longword2 - repeated_one) & ~longword2))
& (repeated_one << 7)) != 0)
break;
longword_ptr++;
}
char_ptr = (const unsigned char *) longword_ptr;
/* At this point, we know that one of the sizeof (longword) bytes
starting at char_ptr is == 0 or == c. On little-endian machines,
we could determine the first such byte without any further memory
accesses, just by looking at the tmp result from the last loop
iteration. But this does not work on big-endian machines.
Choose code that works in both cases. */
char_ptr = (unsigned char *) longword_ptr;
while (*char_ptr && (*char_ptr != c))
char_ptr++;
return (char *) char_ptr;
}

View file

@ -24,9 +24,6 @@
* It also doesn't worry about multi-byte characters.
* So there.
*
* This file is also shipped with GAWK (GNU Awk), gawk specific bits of
* code are included if GAWK is defined.
*
* Arnold Robbins
* January, February, March, 1991
* Updated March, April 1992
@ -39,6 +36,8 @@
* Updated July, 1997
* Updated October, 1999
* Updated September, 2000
* Updated December, 2001
* Updated January, 2011
*
* Fixes from ado@elsie.nci.nih.gov,
* February 1991, May 1992
@ -54,14 +53,15 @@
* July 1997
* Moved to C99 specification.
* September 2000
* Fixes from Tanaka Akira <akr@m17n.org>
* December 2001
*/
#include <config.h>
#ifndef GAWK
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#endif
#if defined(TM_IN_SYS_TIME)
#include <sys/types.h>
#include <sys/time.h>
@ -74,9 +74,7 @@
#define SUNOS_EXT 1 /* stuff in SunOS strftime routine */
#define VMS_EXT 1 /* include %v for VMS date format */
#define HPUX_EXT 1 /* non-conflicting stuff in HP-UX date */
#ifndef GAWK
#define POSIX_SEMANTICS 1 /* call tzset() if TZ changes */
#endif
#undef strchr /* avoid AIX weirdness */
@ -114,6 +112,11 @@ extern int timezone, altzone;
#undef min /* just in case */
/* format for %+ -- currently unused */
#ifndef NATIONAL_FORMAT
#define NATIONAL_FORMAT "%a %b %e %H:%M:%S %Z %Y"
#endif
/* min --- return minimum of two numbers */
static inline int
@ -141,7 +144,8 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
char *start = s;
auto char tbuf[100];
long off;
int i, w, y;
int i, w;
long y;
static short first = 1;
#ifdef POSIX_SEMANTICS
static char *savetz = NULL;
@ -282,7 +286,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
case 'C':
century:
sprintf(tbuf, "%02d", (timeptr->tm_year + 1900) / 100);
sprintf(tbuf, "%02ld", (timeptr->tm_year + 1900L) / 100);
break;
case 'd': /* day of the month, 01 - 31 */
@ -319,16 +323,16 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
*/
w = iso8601wknum(timeptr);
if (timeptr->tm_mon == 11 && w == 1)
y = 1900 + timeptr->tm_year + 1;
y = 1900L + timeptr->tm_year + 1;
else if (timeptr->tm_mon == 0 && w >= 52)
y = 1900 + timeptr->tm_year - 1;
y = 1900L + timeptr->tm_year - 1;
else
y = 1900 + timeptr->tm_year;
y = 1900L + timeptr->tm_year;
if (*format == 'G')
sprintf(tbuf, "%d", y);
sprintf(tbuf, "%ld", y);
else
sprintf(tbuf, "%02d", y % 100);
sprintf(tbuf, "%02ld", y % 100);
break;
case 'h': /* abbreviated month name */
@ -387,7 +391,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
strftime(tbuf, sizeof tbuf, "%H:%M", timeptr);
break;
#if defined(HAVE_MKTIME) || defined(GAWK)
#if defined(HAVE_MKTIME)
case 's': /* time as seconds since the Epoch */
{
struct tm non_const_timeptr;
@ -396,7 +400,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
sprintf(tbuf, "%ld", mktime(& non_const_timeptr));
break;
}
#endif /* defined(HAVE_MKTIME) || defined(GAWK) */
#endif /* defined(HAVE_MKTIME) */
case 'S': /* second, 00 - 60 */
i = range(0, timeptr->tm_sec, 60);
@ -452,7 +456,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
case 'Y': /* year with century */
fullyear:
sprintf(tbuf, "%d", 1900 + timeptr->tm_year);
sprintf(tbuf, "%ld", 1900L + timeptr->tm_year);
break;
/*
@ -495,6 +499,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
# ifdef HPUX
off = -timezone / 60;
# else
/* ADR: 4 August 2001, fixed this per gazelle@interaccess.com */
off = -(daylight ? altzone : timezone) / 60;
# endif /* !HPUX */
#else /* !HAVE_TZNAME */
@ -509,7 +514,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
} else {
tbuf[0] = '+';
}
sprintf(tbuf+1, "%02d%02d", off/60, off%60);
sprintf(tbuf+1, "%02ld%02ld", off/60, off%60);
break;
case 'Z': /* time zone name or abbrevation */
@ -558,10 +563,10 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
#ifdef VMS_EXT
case 'v': /* date as dd-bbb-YYYY */
sprintf(tbuf, "%2d-%3.3s-%4d",
sprintf(tbuf, "%2d-%3.3s-%4ld",
range(1, timeptr->tm_mday, 31),
months_a[range(0, timeptr->tm_mon, 11)],
timeptr->tm_year + 1900);
timeptr->tm_year + 1900L);
for (i = 3; i < 6; i++)
if (islower(tbuf[i]))
tbuf[i] = toupper(tbuf[i]);
@ -594,7 +599,7 @@ out:
/* isleap --- is a year a leap year? */
static int
isleap(int year)
isleap(long year)
{
return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}
@ -677,7 +682,7 @@ iso8601wknum(const struct tm *timeptr)
dec31ly.tm_mon = 11;
dec31ly.tm_mday = 31;
dec31ly.tm_wday = (jan1day == 0) ? 6 : jan1day - 1;
dec31ly.tm_yday = 364 + isleap(dec31ly.tm_year + 1900);
dec31ly.tm_yday = 364 + isleap(dec31ly.tm_year + 1900L);
weeknum = iso8601wknum(& dec31ly);
#endif
}

View file

@ -1,6 +1,6 @@
/* strtrans.c - Translate and untranslate strings with ANSI-C escape sequences. */
/* Copyright (C) 2000 Free Software Foundation, Inc.
/* Copyright (C) 2000-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -51,11 +51,16 @@ ansicstr (string, len, flags, sawc, rlen)
{
int c, temp;
char *ret, *r, *s;
unsigned long v;
if (string == 0 || *string == '\0')
return ((char *)NULL);
#if defined (HANDLE_MULTIBYTE)
ret = (char *)xmalloc (4*len + 1);
#else
ret = (char *)xmalloc (2*len + 1); /* 2*len for possible CTLESC */
#endif
for (r = ret, s = string; s && *s; )
{
c = *s++;
@ -128,6 +133,29 @@ ansicstr (string, len, flags, sawc, rlen)
}
c &= 0xFF;
break;
#if defined (HANDLE_MULTIBYTE)
case 'u':
case 'U':
temp = (c == 'u') ? 4 : 8; /* \uNNNN \UNNNNNNNN */
for (v = 0; ISXDIGIT ((unsigned char)*s) && temp--; s++)
v = (v * 16) + HEXVALUE (*s);
if (temp == ((c == 'u') ? 4 : 8))
{
*r++ = '\\'; /* c remains unchanged */
break;
}
else if (v <= UCHAR_MAX)
{
c = v;
break;
}
else
{
temp = u32cconv (v, r);
r += temp;
continue;
}
#endif
case '\\':
break;
case '\'': case '"': case '?':
@ -143,9 +171,13 @@ ansicstr (string, len, flags, sawc, rlen)
*rlen = r - ret;
return ret;
}
else if ((flags & 1) == 0 && *s == 0)
; /* pass \c through */
else if ((flags & 1) == 0 && (c = *s))
{
s++;
if ((flags & 2) && c == '\\' && c == *s)
s++; /* Posix requires $'\c\\' do backslash escaping */
c = TOCTRL(c);
break;
}

View file

@ -40,7 +40,7 @@
extern int errno;
#endif
#define BASEOPENFLAGS (O_CREAT | O_TRUNC | O_EXCL)
#define BASEOPENFLAGS (O_CREAT | O_TRUNC | O_EXCL | O_BINARY)
#define DEFAULT_TMPDIR "." /* bogus default, should be changed */
#define DEFAULT_NAMEROOT "shtmp"

235
lib/sh/unicode.c Normal file
View file

@ -0,0 +1,235 @@
/* unicode.c - functions to convert unicode characters */
/* Copyright (C) 2010 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/>.
*/
#include <config.h>
#if defined (HANDLE_MULTIBYTE)
#include <stdc.h>
#include <wchar.h>
#include <bashansi.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <limits.h>
#if HAVE_ICONV
# include <iconv.h>
#endif
#include <xmalloc.h>
#ifndef USHORT_MAX
# ifdef USHRT_MAX
# define USHORT_MAX USHRT_MAX
# else
# define USHORT_MAX ((unsigned short) ~(unsigned short)0)
# endif
#endif
#if !defined (STREQ)
# define STREQ(a, b) ((a)[0] == (b)[0] && strcmp ((a), (b)) == 0)
#endif /* !STREQ */
#if defined (HAVE_LOCALE_CHARSET)
extern const char *locale_charset __P((void));
#else
extern char *get_locale_var __P((char *));
#endif
static int u32init = 0;
static int utf8locale = 0;
#if defined (HAVE_ICONV)
static iconv_t localconv;
#endif
#ifndef HAVE_LOCALE_CHARSET
static char *
stub_charset ()
{
char *locale, *s, *t;
locale = get_locale_var ("LC_CTYPE");
if (locale == 0 || *locale == 0)
return "ASCII";
s = strrchr (locale, '.');
if (s)
{
t = strchr (s, '@');
if (t)
*t = 0;
return ++s;
}
else if (STREQ (locale, "UTF-8"))
return "UTF-8";
else
return "ASCII";
}
#endif
/* u32toascii ? */
int
u32tochar (wc, s)
wchar_t wc;
char *s;
{
unsigned long x;
int l;
x = wc;
l = (x <= UCHAR_MAX) ? 1 : ((x <= USHORT_MAX) ? 2 : 4);
if (x <= UCHAR_MAX)
s[0] = x & 0xFF;
else if (x <= USHORT_MAX) /* assume unsigned short = 16 bits */
{
s[0] = (x >> 8) & 0xFF;
s[1] = x & 0xFF;
}
else
{
s[0] = (x >> 24) & 0xFF;
s[1] = (x >> 16) & 0xFF;
s[2] = (x >> 8) & 0xFF;
s[3] = x & 0xFF;
}
s[l] = '\0';
return l;
}
int
u32toutf8 (wc, s)
wchar_t wc;
char *s;
{
int l;
l = (wc < 0x0080) ? 1 : ((wc < 0x0800) ? 2 : 3);
if (wc < 0x0080)
s[0] = (unsigned char)wc;
else if (wc < 0x0800)
{
s[0] = (wc >> 6) | 0xc0;
s[1] = (wc & 0x3f) | 0x80;
}
else
{
s[0] = (wc >> 12) | 0xe0;
s[1] = ((wc >> 6) & 0x3f) | 0x80;
s[2] = (wc & 0x3f) | 0x80;
}
s[l] = '\0';
return l;
}
/* convert a single unicode-32 character into a multibyte string and put the
result in S, which must be large enough (at least MB_LEN_MAX bytes) */
int
u32cconv (c, s)
unsigned long c;
char *s;
{
wchar_t wc;
int n;
#if HAVE_ICONV
const char *charset;
char obuf[25], *optr;
size_t obytesleft;
const char *iptr;
size_t sn;
#endif
wc = c;
#if __STDC_ISO_10646__
if (sizeof (wchar_t) == 4)
{
n = wctomb (s, wc);
return n;
}
#endif
#if HAVE_NL_LANGINFO
codeset = nl_langinfo (CODESET);
if (STREQ (codeset, "UTF-8"))
{
n = u32toutf8 (wc, s);
return n;
}
#endif
#if HAVE_ICONV
/* this is mostly from coreutils-8.5/lib/unicodeio.c */
if (u32init == 0)
{
# if HAVE_LOCALE_CHARSET
charset = locale_charset (); /* XXX - fix later */
# else
charset = stub_charset ();
# endif
if (STREQ (charset, "UTF-8"))
utf8locale = 1;
else
{
localconv = iconv_open (charset, "UTF-8");
if (localconv == (iconv_t)-1)
localconv = iconv_open (charset, "ASCII");
}
u32init = 1;
}
if (utf8locale)
{
n = u32toutf8 (wc, s);
return n;
}
if (localconv == (iconv_t)-1)
{
n = u32tochar (wc, s);
return n;
}
n = u32toutf8 (wc, s);
optr = obuf;
obytesleft = sizeof (obuf);
iptr = s;
sn = n;
iconv (localconv, NULL, NULL, NULL, NULL);
if (iconv (localconv, (ICONV_CONST char **)&iptr, &sn, &optr, &obytesleft) == (size_t)-1)
return n; /* You get utf-8 if iconv fails */
*optr = '\0';
/* number of chars to be copied is optr - obuf if we want to do bounds
checking */
strcpy (s, obuf);
return (optr - obuf);
#endif
n = u32tochar (wc, s); /* fallback */
return n;
}
#endif /* HANDLE_MULTIBYTE */

46
lib/sh/wcswidth.c Normal file
View file

@ -0,0 +1,46 @@
/* wcswidth.c - compute display width of wide character string */
/* Copyright (C) 2010 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/>.
*/
#include <config.h>
#if defined (HANDLE_MULTIBYTE) && !defined (HAVE_WCSWIDTH)
#include <stdc.h>
#include <wchar.h>
#include <bashansi.h>
int
wcswidth(pwcs, n)
const wchar_t *pwcs;
size_t n;
{
wchar_t wc;
int len, l;
len = 0;
while (n-- > 0 && (wc = *pwcs++) != L'\0')
{
if ((l = wcwidth(wc)) < 0)
return (-1);
len += l;
}
return (len);
}
#endif

View file

@ -378,7 +378,7 @@ tilde_expand_word (filename)
{
dirname = glue_prefix_and_suffix (expansion, filename, user_len);
xfree (username);
free (expansion);
xfree (expansion);
return (dirname);
}
}
@ -401,7 +401,7 @@ tilde_expand_word (filename)
if (expansion)
{
dirname = glue_prefix_and_suffix (expansion, filename, user_len);
free (expansion);
xfree (expansion);
}
}
/* If we don't have a failure hook, or if the failure hook did not