Bash-4.3 distribution sources and documentation
This commit is contained in:
parent
4539d736f1
commit
ac50fbac37
497 changed files with 129395 additions and 87598 deletions
347
lib/glob/glob.c
347
lib/glob/glob.c
|
@ -48,6 +48,8 @@
|
|||
#include "stdc.h"
|
||||
#include "memalloc.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "shell.h"
|
||||
|
||||
#include "glob.h"
|
||||
|
@ -84,6 +86,8 @@ struct globval
|
|||
extern void throw_to_top_level __P((void));
|
||||
extern int sh_eaccess __P((char *, int));
|
||||
extern char *sh_makepath __P((const char *, const char *, int));
|
||||
extern int signal_is_pending __P((int));
|
||||
extern void run_pending_traps __P((void));
|
||||
|
||||
extern int extended_glob;
|
||||
|
||||
|
@ -112,9 +116,13 @@ static void wdequote_pathname __P((char *));
|
|||
# define dequote_pathname udequote_pathname
|
||||
#endif
|
||||
static void dequote_pathname __P((char *));
|
||||
static int glob_testdir __P((char *));
|
||||
static int glob_testdir __P((char *, int));
|
||||
static char **glob_dir_to_array __P((char *, char **, int));
|
||||
|
||||
/* Make sure these names continue to agree with what's in smatch.c */
|
||||
extern char *glob_patscan __P((char *, char *, int));
|
||||
extern wchar_t *glob_patscan_wc __P((wchar_t *, wchar_t *, int));
|
||||
|
||||
/* Compile `glob_loop.c' for single-byte characters. */
|
||||
#define CHAR unsigned char
|
||||
#define INT int
|
||||
|
@ -162,15 +170,67 @@ glob_pattern_p (pattern)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if EXTENDED_GLOB
|
||||
/* Return 1 if all subpatterns in the extended globbing pattern PAT indicate
|
||||
that the name should be skipped. XXX - doesn't handle pattern negation,
|
||||
not sure if it should */
|
||||
static int
|
||||
extglob_skipname (pat, dname, flags)
|
||||
char *pat, *dname;
|
||||
int flags;
|
||||
{
|
||||
char *pp, *pe, *t;
|
||||
int n, r;
|
||||
|
||||
pp = pat + 2;
|
||||
pe = pp + strlen (pp) - 1; /*(*/
|
||||
if (*pe != ')')
|
||||
return 0;
|
||||
if ((t = strchr (pp, '|')) == 0) /* easy case first */
|
||||
{
|
||||
*pe = '\0';
|
||||
r = skipname (pp, dname, flags); /*(*/
|
||||
*pe = ')';
|
||||
return r;
|
||||
}
|
||||
while (t = glob_patscan (pp, pe, '|'))
|
||||
{
|
||||
n = t[-1];
|
||||
t[-1] = '\0';
|
||||
r = skipname (pp, dname, flags);
|
||||
t[-1] = n;
|
||||
if (r == 0) /* if any pattern says not skip, we don't skip */
|
||||
return r;
|
||||
pp = t;
|
||||
} /*(*/
|
||||
|
||||
if (pp == pe) /* glob_patscan might find end of pattern */
|
||||
return r;
|
||||
|
||||
*pe = '\0';
|
||||
# if defined (HANDLE_MULTIBYTE)
|
||||
r = mbskipname (pp, dname, flags); /*(*/
|
||||
# else
|
||||
r = skipname (pp, dname, flags); /*(*/
|
||||
# endif
|
||||
*pe = ')';
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return 1 if DNAME should be skipped according to PAT. Mostly concerned
|
||||
with matching leading `.'. */
|
||||
|
||||
static int
|
||||
skipname (pat, dname, flags)
|
||||
char *pat;
|
||||
char *dname;
|
||||
int flags;
|
||||
{
|
||||
#if EXTENDED_GLOB
|
||||
if (extglob_pattern_p (pat)) /* XXX */
|
||||
return (extglob_skipname (pat, dname, flags));
|
||||
#endif
|
||||
|
||||
/* If a leading dot need not be explicitly matched, and the pattern
|
||||
doesn't start with a `.', don't match `.' or `..' */
|
||||
if (noglob_dot_filenames == 0 && pat[0] != '.' &&
|
||||
|
@ -179,7 +239,7 @@ skipname (pat, dname, flags)
|
|||
(dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0'))))
|
||||
return 1;
|
||||
|
||||
/* If a dot must be explicity matched, check to see if they do. */
|
||||
/* If a dot must be explicitly matched, check to see if they do. */
|
||||
else if (noglob_dot_filenames && dname[0] == '.' && pat[0] != '.' &&
|
||||
(pat[0] != '\\' || pat[1] != '.'))
|
||||
return 1;
|
||||
|
@ -188,18 +248,91 @@ skipname (pat, dname, flags)
|
|||
}
|
||||
|
||||
#if HANDLE_MULTIBYTE
|
||||
|
||||
static int
|
||||
wchkname (pat_wc, dn_wc)
|
||||
wchar_t *pat_wc, *dn_wc;
|
||||
{
|
||||
/* If a leading dot need not be explicitly matched, and the
|
||||
pattern doesn't start with a `.', don't match `.' or `..' */
|
||||
if (noglob_dot_filenames == 0 && pat_wc[0] != L'.' &&
|
||||
(pat_wc[0] != L'\\' || pat_wc[1] != L'.') &&
|
||||
(dn_wc[0] == L'.' &&
|
||||
(dn_wc[1] == L'\0' || (dn_wc[1] == L'.' && dn_wc[2] == L'\0'))))
|
||||
return 1;
|
||||
|
||||
/* If a leading dot must be explicitly matched, check to see if the
|
||||
pattern and dirname both have one. */
|
||||
else if (noglob_dot_filenames && dn_wc[0] == L'.' &&
|
||||
pat_wc[0] != L'.' &&
|
||||
(pat_wc[0] != L'\\' || pat_wc[1] != L'.'))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wextglob_skipname (pat, dname, flags)
|
||||
wchar_t *pat, *dname;
|
||||
int flags;
|
||||
{
|
||||
#if EXTENDED_GLOB
|
||||
wchar_t *pp, *pe, *t, n;
|
||||
int r;
|
||||
|
||||
pp = pat + 2;
|
||||
pe = pp + wcslen (pp) - 1; /*(*/
|
||||
if (*pe != L')')
|
||||
return 0;
|
||||
if ((t = wcschr (pp, L'|')) == 0)
|
||||
{
|
||||
*pe = L'\0';
|
||||
r = wchkname (pp, dname); /*(*/
|
||||
*pe = L')';
|
||||
return r;
|
||||
}
|
||||
while (t = glob_patscan_wc (pp, pe, '|'))
|
||||
{
|
||||
n = t[-1];
|
||||
t[-1] = L'\0';
|
||||
r = wchkname (pp, dname);
|
||||
t[-1] = n;
|
||||
if (r == 0)
|
||||
return 0;
|
||||
pp = t;
|
||||
}
|
||||
|
||||
if (pp == pe) /* glob_patscan_wc might find end of pattern */
|
||||
return r;
|
||||
|
||||
*pe = L'\0';
|
||||
r = wchkname (pp, dname); /*(*/
|
||||
*pe = L')';
|
||||
return r;
|
||||
#else
|
||||
return (wchkname (pat, dname));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return 1 if DNAME should be skipped according to PAT. Handles multibyte
|
||||
characters in PAT and DNAME. Mostly concerned with matching leading `.'. */
|
||||
|
||||
static int
|
||||
mbskipname (pat, dname, flags)
|
||||
char *pat, *dname;
|
||||
int flags;
|
||||
{
|
||||
int ret;
|
||||
int ret, ext;
|
||||
wchar_t *pat_wc, *dn_wc;
|
||||
size_t pat_n, dn_n;
|
||||
|
||||
if (mbsmbchar (dname) == 0 && mbsmbchar (pat) == 0)
|
||||
return (skipname (pat, dname, flags));
|
||||
|
||||
ext = 0;
|
||||
#if EXTENDED_GLOB
|
||||
ext = extglob_pattern_p (pat);
|
||||
#endif
|
||||
|
||||
pat_wc = dn_wc = (wchar_t *)NULL;
|
||||
|
||||
pat_n = xdupmbstowcs (&pat_wc, NULL, pat);
|
||||
|
@ -208,22 +341,7 @@ mbskipname (pat, dname, flags)
|
|||
|
||||
ret = 0;
|
||||
if (pat_n != (size_t)-1 && dn_n !=(size_t)-1)
|
||||
{
|
||||
/* If a leading dot need not be explicitly matched, and the
|
||||
pattern doesn't start with a `.', don't match `.' or `..' */
|
||||
if (noglob_dot_filenames == 0 && pat_wc[0] != L'.' &&
|
||||
(pat_wc[0] != L'\\' || pat_wc[1] != L'.') &&
|
||||
(dn_wc[0] == L'.' &&
|
||||
(dn_wc[1] == L'\0' || (dn_wc[1] == L'.' && dn_wc[2] == L'\0'))))
|
||||
ret = 1;
|
||||
|
||||
/* If a leading dot must be explicity matched, check to see if the
|
||||
pattern and dirname both have one. */
|
||||
else if (noglob_dot_filenames && dn_wc[0] == L'.' &&
|
||||
pat_wc[0] != L'.' &&
|
||||
(pat_wc[0] != L'\\' || pat_wc[1] != L'.'))
|
||||
ret = 1;
|
||||
}
|
||||
ret = ext ? wextglob_skipname (pat_wc, dn_wc, flags) : wchkname (pat_wc, dn_wc);
|
||||
else
|
||||
ret = skipname (pat, dname, flags);
|
||||
|
||||
|
@ -325,13 +443,20 @@ dequote_pathname (pathname)
|
|||
|
||||
/* Return 0 if DIR is a directory, -1 otherwise. */
|
||||
static int
|
||||
glob_testdir (dir)
|
||||
glob_testdir (dir, flags)
|
||||
char *dir;
|
||||
int flags;
|
||||
{
|
||||
struct stat finfo;
|
||||
int r;
|
||||
|
||||
/*itrace("glob_testdir: testing %s", dir);*/
|
||||
if (stat (dir, &finfo) < 0)
|
||||
/*itrace("glob_testdir: testing %s" flags = %d, dir, flags);*/
|
||||
#if defined (HAVE_LSTAT)
|
||||
r = (flags & GX_ALLDIRS) ? lstat (dir, &finfo) : stat (dir, &finfo);
|
||||
#else
|
||||
r = stat (dir, &finfo);
|
||||
#endif
|
||||
if (r < 0)
|
||||
return (-1);
|
||||
|
||||
if (S_ISDIR (finfo.st_mode) == 0)
|
||||
|
@ -407,7 +532,6 @@ finddirs (pat, sdir, flags, ep, np)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Return a vector of names of files in directory DIR
|
||||
whose names match glob pattern PAT.
|
||||
|
@ -456,7 +580,7 @@ glob_vector (pat, dir, flags)
|
|||
/* If PAT is empty, skip the loop, but return one (empty) filename. */
|
||||
if (pat == 0 || *pat == '\0')
|
||||
{
|
||||
if (glob_testdir (dir) < 0)
|
||||
if (glob_testdir (dir, 0) < 0)
|
||||
return ((char **) &glob_error_return);
|
||||
|
||||
nextlink = (struct globval *)alloca (sizeof (struct globval));
|
||||
|
@ -478,7 +602,7 @@ glob_vector (pat, dir, flags)
|
|||
skip = 1;
|
||||
}
|
||||
|
||||
patlen = strlen (pat);
|
||||
patlen = (pat && *pat) ? strlen (pat) : 0;
|
||||
|
||||
/* If the filename pattern (PAT) does not contain any globbing characters,
|
||||
we can dispense with reading the directory, and just see if there is
|
||||
|
@ -489,14 +613,18 @@ glob_vector (pat, dir, flags)
|
|||
int dirlen;
|
||||
struct stat finfo;
|
||||
|
||||
if (glob_testdir (dir) < 0)
|
||||
if (glob_testdir (dir, 0) < 0)
|
||||
return ((char **) &glob_error_return);
|
||||
|
||||
dirlen = strlen (dir);
|
||||
nextname = (char *)malloc (dirlen + patlen + 2);
|
||||
npat = (char *)malloc (patlen + 1);
|
||||
if (nextname == 0 || npat == 0)
|
||||
lose = 1;
|
||||
{
|
||||
FREE (nextname);
|
||||
FREE (npat);
|
||||
lose = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (npat, pat);
|
||||
|
@ -518,7 +646,10 @@ glob_vector (pat, dir, flags)
|
|||
count = 1;
|
||||
}
|
||||
else
|
||||
lose = 1;
|
||||
{
|
||||
free (npat);
|
||||
lose = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -536,7 +667,7 @@ glob_vector (pat, dir, flags)
|
|||
is not robust (i.e., it opens non-directories successfully), test
|
||||
that DIR is a directory and punt if it's not. */
|
||||
#if defined (OPENDIR_NOT_ROBUST)
|
||||
if (glob_testdir (dir) < 0)
|
||||
if (glob_testdir (dir, 0) < 0)
|
||||
return ((char **) &glob_error_return);
|
||||
#endif
|
||||
|
||||
|
@ -570,7 +701,12 @@ glob_vector (pat, dir, flags)
|
|||
lose = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
else if (signal_is_pending (SIGINT)) /* XXX - make SIGINT traps responsive */
|
||||
{
|
||||
lose = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
dp = readdir (d);
|
||||
if (dp == NULL)
|
||||
break;
|
||||
|
@ -599,7 +735,7 @@ glob_vector (pat, dir, flags)
|
|||
if (flags & GX_NULLDIR)
|
||||
pflags |= MP_IGNDOT;
|
||||
subdir = sh_makepath (dir, dp->d_name, pflags);
|
||||
isdir = glob_testdir (subdir);
|
||||
isdir = glob_testdir (subdir, flags);
|
||||
if (isdir < 0 && (flags & GX_MATCHDIRS))
|
||||
{
|
||||
free (subdir);
|
||||
|
@ -635,6 +771,8 @@ glob_vector (pat, dir, flags)
|
|||
nextname = (char *) malloc (sdlen + 1);
|
||||
if (nextlink == 0 || nextname == 0)
|
||||
{
|
||||
FREE (nextlink);
|
||||
FREE (nextname);
|
||||
free (subdir);
|
||||
lose = 1;
|
||||
break;
|
||||
|
@ -647,6 +785,8 @@ glob_vector (pat, dir, flags)
|
|||
++count;
|
||||
continue;
|
||||
}
|
||||
else if (flags & GX_MATCHDIRS)
|
||||
free (subdir);
|
||||
|
||||
convfn = fnx_fromfs (dp->d_name, D_NAMLEN (dp));
|
||||
if (strmatch (pat, convfn, mflags) != FNM_NOMATCH)
|
||||
|
@ -666,6 +806,8 @@ glob_vector (pat, dir, flags)
|
|||
nextname = (char *) malloc (D_NAMLEN (dp) + 1);
|
||||
if (nextlink == 0 || nextname == 0)
|
||||
{
|
||||
FREE (nextlink);
|
||||
FREE (nextname);
|
||||
lose = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -689,7 +831,11 @@ glob_vector (pat, dir, flags)
|
|||
nextname = (char *)malloc (sdlen + 1);
|
||||
nextlink = (struct globval *) malloc (sizeof (struct globval));
|
||||
if (nextlink == 0 || nextname == 0)
|
||||
lose = 1;
|
||||
{
|
||||
FREE (nextlink);
|
||||
FREE (nextname);
|
||||
lose = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextlink->name = nextname;
|
||||
|
@ -733,7 +879,7 @@ glob_vector (pat, dir, flags)
|
|||
FREE (tmplink);
|
||||
}
|
||||
|
||||
QUIT;
|
||||
/* Don't call QUIT; here; let higher layers deal with it. */
|
||||
|
||||
return ((char **)NULL);
|
||||
}
|
||||
|
@ -815,7 +961,13 @@ glob_dir_to_array (dir, array, flags)
|
|||
result[i] = (char *) malloc (l + strlen (array[i]) + 3);
|
||||
|
||||
if (result[i] == NULL)
|
||||
return (NULL);
|
||||
{
|
||||
int ind;
|
||||
for (ind = 0; ind < i; ind++)
|
||||
free (result[ind]);
|
||||
free (result);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
strcpy (result[i], dir);
|
||||
if (add_slash)
|
||||
|
@ -893,19 +1045,70 @@ glob_filename (pathname, flags)
|
|||
|
||||
/* If directory_name contains globbing characters, then we
|
||||
have to expand the previous levels. Just recurse. */
|
||||
if (glob_pattern_p (directory_name))
|
||||
if (directory_len > 0 && glob_pattern_p (directory_name))
|
||||
{
|
||||
char **directories;
|
||||
char **directories, *d, *p;
|
||||
register unsigned int i;
|
||||
int all_starstar, last_starstar;
|
||||
|
||||
all_starstar = last_starstar = 0;
|
||||
d = directory_name;
|
||||
dflags = flags & ~GX_MARKDIRS;
|
||||
if ((flags & GX_GLOBSTAR) && directory_name[0] == '*' && directory_name[1] == '*' && (directory_name[2] == '/' || directory_name[2] == '\0'))
|
||||
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
|
||||
/* Collapse a sequence of ** patterns separated by one or more slashes
|
||||
to a single ** terminated by a slash or NUL */
|
||||
if ((flags & GX_GLOBSTAR) && d[0] == '*' && d[1] == '*' && (d[2] == '/' || d[2] == '\0'))
|
||||
{
|
||||
p = d;
|
||||
while (d[0] == '*' && d[1] == '*' && (d[2] == '/' || d[2] == '\0'))
|
||||
{
|
||||
p = d;
|
||||
if (d[2])
|
||||
{
|
||||
d += 3;
|
||||
while (*d == '/')
|
||||
d++;
|
||||
if (*d == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*d == 0)
|
||||
all_starstar = 1;
|
||||
d = p;
|
||||
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
|
||||
directory_len = strlen (d);
|
||||
}
|
||||
|
||||
if (directory_name[directory_len - 1] == '/')
|
||||
directory_name[directory_len - 1] = '\0';
|
||||
/* If there is a non [star][star]/ component in directory_name, we
|
||||
still need to collapse trailing sequences of [star][star]/ into
|
||||
a single one and note that the directory name ends with [star][star],
|
||||
so we can compensate if filename is [star][star] */
|
||||
if ((flags & GX_GLOBSTAR) && all_starstar == 0)
|
||||
{
|
||||
int dl, prev;
|
||||
prev = dl = directory_len;
|
||||
while (dl >= 4 && d[dl - 1] == '/' &&
|
||||
d[dl - 2] == '*' &&
|
||||
d[dl - 3] == '*' &&
|
||||
d[dl - 4] == '/')
|
||||
prev = dl, dl -= 3;
|
||||
if (dl != directory_len)
|
||||
last_starstar = 1;
|
||||
directory_len = prev;
|
||||
}
|
||||
|
||||
directories = glob_filename (directory_name, dflags);
|
||||
/* If the directory name ends in [star][star]/ but the filename is
|
||||
[star][star], just remove the final [star][star] from the directory
|
||||
so we don't have to scan everything twice. */
|
||||
if (last_starstar && directory_len > 4 &&
|
||||
filename[0] == '*' && filename[1] == '*' && filename[2] == 0)
|
||||
{
|
||||
directory_len -= 3;
|
||||
}
|
||||
|
||||
if (d[directory_len - 1] == '/')
|
||||
d[directory_len - 1] = '\0';
|
||||
|
||||
directories = glob_filename (d, dflags);
|
||||
|
||||
if (free_dirname)
|
||||
{
|
||||
|
@ -927,13 +1130,26 @@ glob_filename (pathname, flags)
|
|||
return ((char **) &glob_error_return);
|
||||
}
|
||||
|
||||
/* If we have something like [star][star]/[star][star], it's no use to
|
||||
glob **, then do it again, and throw half the results away. */
|
||||
if (all_starstar && filename[0] == '*' && filename[1] == '*' && filename[2] == 0)
|
||||
{
|
||||
free ((char *) directories);
|
||||
free (directory_name);
|
||||
directory_name = NULL;
|
||||
directory_len = 0;
|
||||
goto only_filename;
|
||||
}
|
||||
|
||||
/* We have successfully globbed the preceding directory name.
|
||||
For each name in DIRECTORIES, call glob_vector on it and
|
||||
FILENAME. Concatenate the results together. */
|
||||
for (i = 0; directories[i] != NULL; ++i)
|
||||
{
|
||||
char **temp_results;
|
||||
int shouldbreak;
|
||||
|
||||
shouldbreak = 0;
|
||||
/* XXX -- we've recursively scanned any directories resulting from
|
||||
a `**', so turn off the flag. We turn it on again below if
|
||||
filename is `**' */
|
||||
|
@ -964,8 +1180,39 @@ glob_filename (pathname, flags)
|
|||
|
||||
/* If we're expanding **, we don't need to glue the directory
|
||||
name to the results; we've already done it in glob_vector */
|
||||
if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
|
||||
array = temp_results;
|
||||
if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && (filename[2] == '\0' || filename[2] == '/'))
|
||||
{
|
||||
/* When do we remove null elements from temp_results? And
|
||||
how to avoid duplicate elements in the final result? */
|
||||
/* If (dflags & GX_NULLDIR) glob_filename potentially left a
|
||||
NULL placeholder in the temp results just in case
|
||||
glob_vector/glob_dir_to_array did something with it, but
|
||||
if it didn't, and we're not supposed to be passing them
|
||||
through for some reason ((flags & GX_NULLDIR) == 0) we
|
||||
need to remove all the NULL elements from the beginning
|
||||
of TEMP_RESULTS. */
|
||||
/* If we have a null directory name and ** as the filename,
|
||||
we have just searched for everything from the current
|
||||
directory on down. Break now (shouldbreak = 1) to avoid
|
||||
duplicate entries in the final result. */
|
||||
#define NULL_PLACEHOLDER(x) ((x) && *(x) && **(x) == 0)
|
||||
if ((dflags & GX_NULLDIR) && (flags & GX_NULLDIR) == 0 &&
|
||||
NULL_PLACEHOLDER (temp_results))
|
||||
#undef NULL_PLACEHOLDER
|
||||
{
|
||||
register int i, n;
|
||||
for (n = 0; temp_results[n] && *temp_results[n] == 0; n++)
|
||||
;
|
||||
i = n;
|
||||
do
|
||||
temp_results[i - n] = temp_results[i];
|
||||
while (temp_results[i++] != 0);
|
||||
array = temp_results;
|
||||
shouldbreak = 1;
|
||||
}
|
||||
else
|
||||
array = temp_results;
|
||||
}
|
||||
else
|
||||
array = glob_dir_to_array (directories[i], temp_results, flags);
|
||||
l = 0;
|
||||
|
@ -986,6 +1233,11 @@ glob_filename (pathname, flags)
|
|||
/* Note that the elements of ARRAY are not freed. */
|
||||
if (array != temp_results)
|
||||
free ((char *) array);
|
||||
else if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
|
||||
free (temp_results); /* expanding ** case above */
|
||||
|
||||
if (shouldbreak)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Free the directories. */
|
||||
|
@ -997,6 +1249,7 @@ glob_filename (pathname, flags)
|
|||
return (result);
|
||||
}
|
||||
|
||||
only_filename:
|
||||
/* If there is only a directory name, return it. */
|
||||
if (*filename == '\0')
|
||||
{
|
||||
|
@ -1055,10 +1308,13 @@ glob_filename (pathname, flags)
|
|||
{
|
||||
if (free_dirname)
|
||||
free (directory_name);
|
||||
QUIT; /* XXX - shell */
|
||||
run_pending_traps ();
|
||||
return (temp_results);
|
||||
}
|
||||
|
||||
result = glob_dir_to_array ((dflags & GX_ALLDIRS) ? "" : directory_name, temp_results, flags);
|
||||
|
||||
if (free_dirname)
|
||||
free (directory_name);
|
||||
return (result);
|
||||
|
@ -1079,6 +1335,7 @@ glob_filename (pathname, flags)
|
|||
free (directory_name);
|
||||
|
||||
QUIT;
|
||||
run_pending_traps ();
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ extern int glob_pattern_p __P((const char *));
|
|||
extern char **glob_vector __P((char *, char *, int));
|
||||
extern char **glob_filename __P((char *, int));
|
||||
|
||||
extern int extglob_pattern_p __P((const char *));
|
||||
|
||||
extern char *glob_error_return;
|
||||
extern int noglob_dot_filenames;
|
||||
extern int glob_ignore_case;
|
||||
|
|
|
@ -200,6 +200,24 @@ bad_bracket:
|
|||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
extglob_pattern_p (pat)
|
||||
char *pat;
|
||||
{
|
||||
switch (pat[0])
|
||||
{
|
||||
case '*':
|
||||
case '+':
|
||||
case '!':
|
||||
case '@':
|
||||
return (pat[1] == LPAREN);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return 1 of the first character of STRING could match the first
|
||||
character of pattern PAT. Used to avoid n2 calls to strmatch(). */
|
||||
int
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 1991-2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991-2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -22,7 +22,8 @@ static int GMATCH __P((CHAR *, CHAR *, CHAR *, CHAR *, int));
|
|||
static CHAR *PARSE_COLLSYM __P((CHAR *, INT *));
|
||||
static CHAR *BRACKMATCH __P((CHAR *, U_CHAR, int));
|
||||
static int EXTMATCH __P((INT, CHAR *, CHAR *, CHAR *, CHAR *, int));
|
||||
static CHAR *PATSCAN __P((CHAR *, CHAR *, INT));
|
||||
|
||||
/*static*/ CHAR *PATSCAN __P((CHAR *, CHAR *, INT));
|
||||
|
||||
int
|
||||
FCT (pattern, string, flags)
|
||||
|
@ -144,8 +145,9 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
|
|||
if (EXTMATCH (c, newn, se, p, pe, flags) == 0)
|
||||
return (0);
|
||||
}
|
||||
/* We didn't match. If we have a `?(...)', that's failure. */
|
||||
return FNM_NOMATCH;
|
||||
/* We didn't match. If we have a `?(...)', we can match 0
|
||||
or 1 times. */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
else if (c == L('?'))
|
||||
|
@ -191,6 +193,18 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
|
|||
if (p == pe && (c == L('?') || c == L('*')))
|
||||
return (0);
|
||||
|
||||
/* If we've hit the end of the string and the rest of the pattern
|
||||
is something that matches the empty string, we can succeed. */
|
||||
#if defined (EXTENDED_GLOB)
|
||||
if (n == se && ((flags & FNM_EXTMATCH) && (c == L('!') || c == L('?')) && *p == L('(')))
|
||||
{
|
||||
--p;
|
||||
if (EXTMATCH (c, n, se, p, pe, flags) == 0)
|
||||
return (c == L('!') ? FNM_NOMATCH : 0);
|
||||
return (c == L('!') ? 0 : FNM_NOMATCH);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* General case, use recursion. */
|
||||
{
|
||||
U_CHAR c1;
|
||||
|
@ -290,7 +304,7 @@ BRACKMATCH (p, test, flags)
|
|||
{
|
||||
register CHAR cstart, cend, c;
|
||||
register int not; /* Nonzero if the sense of the character class is inverted. */
|
||||
int brcnt;
|
||||
int brcnt, forcecoll;
|
||||
INT pc;
|
||||
CHAR *savep;
|
||||
|
||||
|
@ -311,6 +325,7 @@ BRACKMATCH (p, test, flags)
|
|||
/* Initialize cstart and cend in case `-' is the last
|
||||
character of the pattern. */
|
||||
cstart = cend = c;
|
||||
forcecoll = 0;
|
||||
|
||||
/* POSIX.2 equivalence class: [=c=]. See POSIX.2 2.8.3.2. Find
|
||||
the end of the equivalence class, move the pattern pointer past
|
||||
|
@ -400,6 +415,7 @@ BRACKMATCH (p, test, flags)
|
|||
range. If it is, we set cstart to one greater than `test',
|
||||
so any comparisons later will fail. */
|
||||
cstart = (pc == INVALID) ? test + 1 : pc;
|
||||
forcecoll = 1;
|
||||
}
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && c == L('\\'))
|
||||
|
@ -443,6 +459,7 @@ BRACKMATCH (p, test, flags)
|
|||
range expression. If we get one, we set cend to one fewer
|
||||
than the test character to make sure the range test fails. */
|
||||
cend = (pc == INVALID) ? test - 1 : pc;
|
||||
forcecoll = 1;
|
||||
}
|
||||
cend = FOLD (cend);
|
||||
|
||||
|
@ -453,7 +470,7 @@ BRACKMATCH (p, test, flags)
|
|||
the expression shall be treated as invalid.'' Note that this
|
||||
applies to only the range expression; the rest of the bracket
|
||||
expression is still checked for matches. */
|
||||
if (RANGECMP (cstart, cend) > 0)
|
||||
if (RANGECMP (cstart, cend, forcecoll) > 0)
|
||||
{
|
||||
if (c == L(']'))
|
||||
break;
|
||||
|
@ -462,7 +479,7 @@ BRACKMATCH (p, test, flags)
|
|||
}
|
||||
}
|
||||
|
||||
if (RANGECMP (test, cstart) >= 0 && RANGECMP (test, cend) <= 0)
|
||||
if (RANGECMP (test, cstart, forcecoll) >= 0 && RANGECMP (test, cend, forcecoll) <= 0)
|
||||
goto matched;
|
||||
|
||||
if (c == L(']'))
|
||||
|
@ -517,7 +534,7 @@ matched:
|
|||
because we're scanning a `patlist'. Otherwise, we scan until we see
|
||||
DELIM. In all cases, we never scan past END. The return value is the
|
||||
first character after the matching DELIM. */
|
||||
static CHAR *
|
||||
/*static*/ CHAR *
|
||||
PATSCAN (string, end, delim)
|
||||
CHAR *string, *end;
|
||||
INT delim;
|
||||
|
@ -530,6 +547,9 @@ PATSCAN (string, end, delim)
|
|||
cchar = 0;
|
||||
bfirst = NULL;
|
||||
|
||||
if (string == end)
|
||||
return (NULL);
|
||||
|
||||
for (s = string; c = *s; s++)
|
||||
{
|
||||
if (s >= end)
|
||||
|
@ -606,19 +626,32 @@ STRCOMPARE (p, pe, s, se)
|
|||
{
|
||||
int ret;
|
||||
CHAR c1, c2;
|
||||
int l1, l2;
|
||||
|
||||
l1 = pe - p;
|
||||
l2 = se - s;
|
||||
|
||||
if (l1 != l2)
|
||||
return (FNM_NOMATCH); /* unequal lengths, can't be identical */
|
||||
|
||||
c1 = *pe;
|
||||
c2 = *se;
|
||||
|
||||
*pe = *se = '\0';
|
||||
if (c1 != 0)
|
||||
*pe = '\0';
|
||||
if (c2 != 0)
|
||||
*se = '\0';
|
||||
|
||||
#if HAVE_MULTIBYTE || defined (HAVE_STRCOLL)
|
||||
ret = STRCOLL ((XCHAR *)p, (XCHAR *)s);
|
||||
#else
|
||||
ret = STRCMP ((XCHAR *)p, (XCHAR *)s);
|
||||
#endif
|
||||
|
||||
*pe = c1;
|
||||
*se = c2;
|
||||
if (c1 != 0)
|
||||
*pe = c1;
|
||||
if (c2 != 0)
|
||||
*se = c2;
|
||||
|
||||
return (ret == 0 ? ret : FNM_NOMATCH);
|
||||
}
|
||||
|
|
|
@ -43,15 +43,25 @@
|
|||
#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
|
||||
#define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
|
||||
|
||||
#ifndef GLOBASCII_DEFAULT
|
||||
# define GLOBASCII_DEFAULT 0
|
||||
#endif
|
||||
|
||||
int glob_asciirange = GLOBASCII_DEFAULT;
|
||||
|
||||
/* We use strcoll(3) for range comparisons in bracket expressions,
|
||||
even though it can have unwanted side effects in locales
|
||||
other than POSIX or US. For instance, in the de locale, [A-Z] matches
|
||||
all characters. */
|
||||
all characters. If GLOB_ASCIIRANGE is non-zero, and we're not forcing
|
||||
the use of strcoll (e.g., for explicit collating symbols), we use
|
||||
straight ordering as if in the C locale. */
|
||||
|
||||
#if defined (HAVE_STRCOLL)
|
||||
/* Helper function for collating symbol equivalence. */
|
||||
static int rangecmp (c1, c2)
|
||||
static int
|
||||
rangecmp (c1, c2, forcecoll)
|
||||
int c1, c2;
|
||||
int forcecoll;
|
||||
{
|
||||
static char s1[2] = { ' ', '\0' };
|
||||
static char s2[2] = { ' ', '\0' };
|
||||
|
@ -64,6 +74,9 @@ static int rangecmp (c1, c2)
|
|||
if (c1 == c2)
|
||||
return (0);
|
||||
|
||||
if (forcecoll == 0 && glob_asciirange)
|
||||
return (c1 - c2);
|
||||
|
||||
s1[0] = c1;
|
||||
s2[0] = c2;
|
||||
|
||||
|
@ -72,7 +85,7 @@ static int rangecmp (c1, c2)
|
|||
return (c1 - c2);
|
||||
}
|
||||
#else /* !HAVE_STRCOLL */
|
||||
# define rangecmp(c1, c2) ((int)(c1) - (int)(c2))
|
||||
# define rangecmp(c1, c2, f) ((int)(c1) - (int)(c2))
|
||||
#endif /* !HAVE_STRCOLL */
|
||||
|
||||
#if defined (HAVE_STRCOLL)
|
||||
|
@ -80,7 +93,7 @@ static int
|
|||
collequiv (c1, c2)
|
||||
int c1, c2;
|
||||
{
|
||||
return (rangecmp (c1, c2) == 0);
|
||||
return (rangecmp (c1, c2, 1) == 0);
|
||||
}
|
||||
#else
|
||||
# define collequiv(c1, c2) ((c1) == (c2))
|
||||
|
@ -214,14 +227,14 @@ is_cclass (c, name)
|
|||
#define COLLSYM collsym
|
||||
#define PARSE_COLLSYM parse_collsym
|
||||
#define BRACKMATCH brackmatch
|
||||
#define PATSCAN patscan
|
||||
#define PATSCAN glob_patscan
|
||||
#define STRCOMPARE strcompare
|
||||
#define EXTMATCH extmatch
|
||||
#define STRCHR(S, C) strchr((S), (C))
|
||||
#define STRCOLL(S1, S2) strcoll((S1), (S2))
|
||||
#define STRLEN(S) strlen(S)
|
||||
#define STRCMP(S1, S2) strcmp((S1), (S2))
|
||||
#define RANGECMP(C1, C2) rangecmp((C1), (C2))
|
||||
#define RANGECMP(C1, C2, F) rangecmp((C1), (C2), (F))
|
||||
#define COLLEQUIV(C1, C2) collequiv((C1), (C2))
|
||||
#define CTYPE_T enum char_class
|
||||
#define IS_CCLASS(C, S) is_cclass((C), (S))
|
||||
|
@ -244,8 +257,9 @@ is_cclass (c, name)
|
|||
extern char *mbsmbchar __P((const char *));
|
||||
|
||||
static int
|
||||
rangecmp_wc (c1, c2)
|
||||
rangecmp_wc (c1, c2, forcecoll)
|
||||
wint_t c1, c2;
|
||||
int forcecoll;
|
||||
{
|
||||
static wchar_t s1[2] = { L' ', L'\0' };
|
||||
static wchar_t s2[2] = { L' ', L'\0' };
|
||||
|
@ -253,6 +267,9 @@ rangecmp_wc (c1, c2)
|
|||
if (c1 == c2)
|
||||
return 0;
|
||||
|
||||
if (forcecoll == 0 && glob_asciirange && c1 <= UCHAR_MAX && c2 <= UCHAR_MAX)
|
||||
return ((int)(c1 - c2));
|
||||
|
||||
s1[0] = c1;
|
||||
s2[0] = c2;
|
||||
|
||||
|
@ -263,7 +280,7 @@ static int
|
|||
collequiv_wc (c, equiv)
|
||||
wint_t c, equiv;
|
||||
{
|
||||
return (!(c - equiv));
|
||||
return (c == equiv);
|
||||
}
|
||||
|
||||
/* Helper function for collating symbol. */
|
||||
|
@ -342,14 +359,14 @@ is_wcclass (wc, name)
|
|||
#define COLLSYM collwcsym
|
||||
#define PARSE_COLLSYM parse_collwcsym
|
||||
#define BRACKMATCH brackmatch_wc
|
||||
#define PATSCAN patscan_wc
|
||||
#define PATSCAN glob_patscan_wc
|
||||
#define STRCOMPARE wscompare
|
||||
#define EXTMATCH extmatch_wc
|
||||
#define STRCHR(S, C) wcschr((S), (C))
|
||||
#define STRCOLL(S1, S2) wcscoll((S1), (S2))
|
||||
#define STRLEN(S) wcslen(S)
|
||||
#define STRCMP(S1, S2) wcscmp((S1), (S2))
|
||||
#define RANGECMP(C1, C2) rangecmp_wc((C1), (C2))
|
||||
#define RANGECMP(C1, C2, F) rangecmp_wc((C1), (C2), (F))
|
||||
#define COLLEQUIV(C1, C2) collequiv_wc((C1), (C2))
|
||||
#define CTYPE_T enum char_class
|
||||
#define IS_CCLASS(C, S) is_wcclass((C), (S))
|
||||
|
@ -369,13 +386,7 @@ xstrmatch (pattern, string, flags)
|
|||
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)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* xmbsrtowcs.c -- replacement function for mbsrtowcs */
|
||||
|
||||
/* Copyright (C) 2002-2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -166,7 +166,7 @@ xdupmbstowcs2 (destp, src)
|
|||
do
|
||||
{
|
||||
end_or_backslash = strchrnul(p, '\\');
|
||||
nms = (end_or_backslash - p);
|
||||
nms = end_or_backslash - p;
|
||||
if (*end_or_backslash == '\0')
|
||||
nms++;
|
||||
|
||||
|
@ -283,6 +283,8 @@ xdupmbstowcs (destp, indicesp, src)
|
|||
{
|
||||
if (destp)
|
||||
*destp = NULL;
|
||||
if (indicesp)
|
||||
*indicesp = NULL;
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
|
@ -298,6 +300,8 @@ xdupmbstowcs (destp, indicesp, src)
|
|||
if (wsbuf == NULL)
|
||||
{
|
||||
*destp = NULL;
|
||||
if (indicesp)
|
||||
*indicesp = NULL;
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
|
@ -309,6 +313,7 @@ xdupmbstowcs (destp, indicesp, src)
|
|||
{
|
||||
free (wsbuf);
|
||||
*destp = NULL;
|
||||
*indicesp = NULL;
|
||||
return (size_t)-1;
|
||||
}
|
||||
}
|
||||
|
@ -343,6 +348,8 @@ xdupmbstowcs (destp, indicesp, src)
|
|||
free (wsbuf);
|
||||
FREE (indices);
|
||||
*destp = NULL;
|
||||
if (indicesp)
|
||||
*indicesp = NULL;
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
|
@ -362,18 +369,22 @@ xdupmbstowcs (destp, indicesp, src)
|
|||
free (wsbuf);
|
||||
FREE (indices);
|
||||
*destp = NULL;
|
||||
if (indicesp)
|
||||
*indicesp = NULL;
|
||||
return (size_t)-1;
|
||||
}
|
||||
wsbuf = wstmp;
|
||||
|
||||
if (indicesp)
|
||||
{
|
||||
idxtmp = (char **) realloc (indices, wsbuf_size * sizeof (char **));
|
||||
idxtmp = (char **) realloc (indices, wsbuf_size * sizeof (char *));
|
||||
if (idxtmp == NULL)
|
||||
{
|
||||
free (wsbuf);
|
||||
free (indices);
|
||||
*destp = NULL;
|
||||
if (indicesp)
|
||||
*indicesp = NULL;
|
||||
return (size_t)-1;
|
||||
}
|
||||
indices = idxtmp;
|
||||
|
|
|
@ -49,13 +49,15 @@ mkinstalldirs = $(SHELL) $(MKINSTALLDIRS)
|
|||
|
||||
l = @INTL_LIBTOOL_SUFFIX_PREFIX@
|
||||
|
||||
AR = ar
|
||||
AR = @AR@
|
||||
CC = @CC@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
RANLIB = @RANLIB@
|
||||
YACC = @INTLBISON@ -y -d
|
||||
YFLAGS = --name-prefix=__gettext
|
||||
|
||||
ARFLAGS = @ARFLAGS@
|
||||
|
||||
LOCAL_DEFS = @LOCAL_DEFS@
|
||||
|
||||
DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \
|
||||
|
@ -146,7 +148,7 @@ all-no-no:
|
|||
|
||||
libintl.a libgnuintl.a: $(OBJECTS)
|
||||
rm -f $@
|
||||
$(AR) cru $@ $(OBJECTS)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJECTS)
|
||||
$(RANLIB) $@
|
||||
|
||||
libintl.la libgnuintl.la: $(OBJECTS)
|
||||
|
|
|
@ -272,7 +272,7 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
|
|||
}
|
||||
if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
|
||||
{
|
||||
/* This component can be part of both syntaces but has different
|
||||
/* This component can be part of both syntaxes but has different
|
||||
leading characters. For CEN we use `+', else `@'. */
|
||||
*cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
|
||||
cp = stpcpy (cp, modifier);
|
||||
|
|
|
@ -305,7 +305,10 @@ read_alias_file (fname, fname_len)
|
|||
|
||||
if (nmap >= maxmap)
|
||||
if (__builtin_expect (extend_alias_table (), 0))
|
||||
return added;
|
||||
{
|
||||
fclose (fp);
|
||||
return added;
|
||||
}
|
||||
|
||||
alias_len = strlen (alias) + 1;
|
||||
value_len = strlen (value) + 1;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#endif
|
||||
|
||||
#if !defined (getpagesize)
|
||||
# ifndef _MINIX
|
||||
# if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
# if defined (PAGESIZE)
|
||||
|
|
|
@ -45,11 +45,11 @@
|
|||
# define NULL 0
|
||||
#endif
|
||||
|
||||
#if !defined (__STRING)
|
||||
#if !defined (CPP_STRING)
|
||||
# if defined (HAVE_STRINGIZE)
|
||||
# define __STRING(x) #x
|
||||
# define CPP_STRING(x) #x
|
||||
# else
|
||||
# define __STRING(x) "x"
|
||||
# define CPP_STRING(x) "x"
|
||||
# endif /* !HAVE_STRINGIZE */
|
||||
#endif /* !__STRING */
|
||||
|
||||
|
@ -165,4 +165,9 @@ do { \
|
|||
# define _(x) x
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
extern void _malloc_block_signals __P((sigset_t *, sigset_t *));
|
||||
extern void _malloc_unblock_signals __P((sigset_t *, sigset_t *));
|
||||
|
||||
#endif /* _IMALLOC_H */
|
||||
|
|
|
@ -172,7 +172,7 @@ typedef union _malloc_guard {
|
|||
#define ASSERT(p) \
|
||||
do \
|
||||
{ \
|
||||
if (!(p)) xbotch((PTR_T)0, ERR_ASSERT_FAILED, __STRING(p), file, line); \
|
||||
if (!(p)) xbotch((PTR_T)0, ERR_ASSERT_FAILED, CPP_STRING(p), file, line); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
|
@ -265,7 +265,7 @@ extern char *sbrk ();
|
|||
#endif /* !HAVE_DECL_SBRK */
|
||||
|
||||
#ifdef SHELL
|
||||
extern int interrupt_immediately;
|
||||
extern int interrupt_immediately, running_trap;
|
||||
extern int signal_is_trapped __P((int));
|
||||
#endif
|
||||
|
||||
|
@ -498,8 +498,8 @@ xsplit (mp, nu)
|
|||
busy[nbuck] = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
block_signals (setp, osetp)
|
||||
void
|
||||
_malloc_block_signals (setp, osetp)
|
||||
sigset_t *setp, *osetp;
|
||||
{
|
||||
#ifdef HAVE_POSIX_SIGNALS
|
||||
|
@ -513,8 +513,8 @@ block_signals (setp, osetp)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
unblock_signals (setp, osetp)
|
||||
void
|
||||
_malloc_unblock_signals (setp, osetp)
|
||||
sigset_t *setp, *osetp;
|
||||
{
|
||||
#ifdef HAVE_POSIX_SIGNALS
|
||||
|
@ -562,10 +562,14 @@ morecore (nu)
|
|||
/* Block all signals in case we are executed from a signal handler. */
|
||||
blocked_sigs = 0;
|
||||
#ifdef SHELL
|
||||
if (interrupt_immediately || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
|
||||
# if defined (SIGCHLD)
|
||||
if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
|
||||
# else
|
||||
if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT))
|
||||
# endif
|
||||
#endif
|
||||
{
|
||||
block_signals (&set, &oset);
|
||||
_malloc_block_signals (&set, &oset);
|
||||
blocked_sigs = 1;
|
||||
}
|
||||
|
||||
|
@ -652,7 +656,7 @@ morecore (nu)
|
|||
|
||||
morecore_done:
|
||||
if (blocked_sigs)
|
||||
unblock_signals (&set, &oset);
|
||||
_malloc_unblock_signals (&set, &oset);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -901,10 +905,10 @@ internal_free (mem, file, line, flags)
|
|||
if (mg.i != p->mh_nbytes)
|
||||
xbotch (mem, ERR_ASSERT_FAILED, _("free: start and end chunk sizes differ"), file, line);
|
||||
|
||||
#if 1
|
||||
if (nunits >= LESSCORE_MIN && ((char *)p + binsize(nunits) == memtop))
|
||||
#if GLIBC21
|
||||
if (nunits >= LESSCORE_MIN && ((char *)p + binsize(nunits) == sbrk (0)))
|
||||
#else
|
||||
if (((char *)p + binsize(nunits) == memtop) && nunits >= LESSCORE_MIN)
|
||||
if (nunits >= LESSCORE_MIN && ((char *)p + binsize(nunits) == memtop))
|
||||
#endif
|
||||
{
|
||||
/* If above LESSCORE_FRC, give back unconditionally. This should be set
|
||||
|
|
|
@ -28,6 +28,11 @@
|
|||
#include "imalloc.h"
|
||||
#include "table.h"
|
||||
|
||||
#ifdef SHELL
|
||||
extern int interrupt_immediately, running_trap;
|
||||
extern int signal_is_trapped __P((int));
|
||||
#endif
|
||||
|
||||
extern int malloc_register;
|
||||
|
||||
#ifdef MALLOC_REGISTER
|
||||
|
@ -168,6 +173,18 @@ mregister_alloc (tag, mem, size, file, line)
|
|||
int line;
|
||||
{
|
||||
mr_table_t *tentry;
|
||||
sigset_t set, oset;
|
||||
int blocked_sigs;
|
||||
|
||||
/* Block all signals in case we are executed from a signal handler. */
|
||||
blocked_sigs = 0;
|
||||
#ifdef SHELL
|
||||
if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
|
||||
#endif
|
||||
{
|
||||
_malloc_block_signals (&set, &oset);
|
||||
blocked_sigs = 1;
|
||||
}
|
||||
|
||||
tentry = find_entry (mem, FIND_ALLOC);
|
||||
|
||||
|
@ -175,6 +192,8 @@ mregister_alloc (tag, mem, size, file, line)
|
|||
{
|
||||
/* oops. table is full. punt. */
|
||||
fprintf (stderr, _("register_alloc: alloc table is full with FIND_ALLOC?\n"));
|
||||
if (blocked_sigs)
|
||||
_malloc_unblock_signals (&set, &oset);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -194,6 +213,9 @@ mregister_alloc (tag, mem, size, file, line)
|
|||
|
||||
if (tentry != &mem_overflow)
|
||||
table_allocated++;
|
||||
|
||||
if (blocked_sigs)
|
||||
_malloc_unblock_signals (&set, &oset);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -204,6 +226,18 @@ mregister_free (mem, size, file, line)
|
|||
int line;
|
||||
{
|
||||
mr_table_t *tentry;
|
||||
sigset_t set, oset;
|
||||
int blocked_sigs;
|
||||
|
||||
/* Block all signals in case we are executed from a signal handler. */
|
||||
blocked_sigs = 0;
|
||||
#ifdef SHELL
|
||||
if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
|
||||
#endif
|
||||
{
|
||||
_malloc_block_signals (&set, &oset);
|
||||
blocked_sigs = 1;
|
||||
}
|
||||
|
||||
tentry = find_entry (mem, FIND_EXIST);
|
||||
if (tentry == 0)
|
||||
|
@ -212,6 +246,8 @@ mregister_free (mem, size, file, line)
|
|||
#if 0
|
||||
fprintf (stderr, "register_free: %p not in allocation table?\n", mem);
|
||||
#endif
|
||||
if (blocked_sigs)
|
||||
_malloc_unblock_signals (&set, &oset);
|
||||
return;
|
||||
}
|
||||
if (tentry->flags & MT_FREE)
|
||||
|
@ -228,6 +264,9 @@ mregister_free (mem, size, file, line)
|
|||
|
||||
if (tentry != &mem_overflow)
|
||||
table_allocated--;
|
||||
|
||||
if (blocked_sigs)
|
||||
_malloc_unblock_signals (&set, &oset);
|
||||
}
|
||||
|
||||
/* If we ever add more flags, this will require changes. */
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# #
|
||||
#############################################################################
|
||||
|
||||
# Copyright (C) 1994-2009 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1994-2012 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
|
||||
|
@ -83,21 +83,24 @@ 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)/colors.c $(srcdir)/parse-colors.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 \
|
||||
posixstat.h posixdir.h posixjmp.h tilde.h rlconf.h rltty.h \
|
||||
ansi_stdlib.h rlstdc.h tcap.h xmalloc.h rlprivate.h rlshell.h \
|
||||
rltypedefs.h rlmbutil.h
|
||||
rltypedefs.h rlmbutil.h colors.h parse-colors.h
|
||||
|
||||
HISTOBJ = history.o histexpand.o histfile.o histsearch.o shell.o savestring.o \
|
||||
mbutil.o
|
||||
TILDEOBJ = tilde.o
|
||||
COLORSOBJ = colors.o parse-colors.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 xfree.o compat.o
|
||||
text.o nls.o misc.o $(HISTOBJ) $(TILDEOBJ) $(COLORSOBJ) \
|
||||
xmalloc.o xfree.o compat.o
|
||||
|
||||
# The texinfo files which document this library.
|
||||
DOCSOURCE = doc/rlman.texinfo doc/rltech.texinfo doc/rluser.texinfo
|
||||
|
@ -176,6 +179,7 @@ compat.o: rlstdc.h
|
|||
complete.o: ansi_stdlib.h posixdir.h posixstat.h
|
||||
complete.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
complete.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
|
||||
complete.o: colors.h
|
||||
display.o: ansi_stdlib.h posixstat.h
|
||||
display.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
display.o: tcap.h
|
||||
|
@ -264,6 +268,14 @@ 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
|
||||
|
||||
colors.o: ${BUILD_DIR}/config.h colors.h
|
||||
colors.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
|
||||
colors.o: rlconf.h
|
||||
colors.o: ansi_stdlib.h posixstat.h
|
||||
parse-colors.o: ${BUILD_DIR}/config.h colors.h parse-colors.h
|
||||
parse-colors.o: rldefs.h rlconf.h
|
||||
parse-colors.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
|
||||
|
||||
bind.o: rlshell.h
|
||||
histfile.o: rlshell.h
|
||||
nls.o: rlshell.h
|
||||
|
@ -293,6 +305,8 @@ text.o: rlprivate.h
|
|||
undo.o: rlprivate.h
|
||||
util.o: rlprivate.h
|
||||
vi_mode.o: rlprivate.h
|
||||
colors.o: rlprivate.h
|
||||
parse-colors.o: rlprivate.h
|
||||
|
||||
bind.o: xmalloc.h
|
||||
complete.o: xmalloc.h
|
||||
|
@ -320,6 +334,8 @@ util.o: xmalloc.h
|
|||
vi_mode.o: xmalloc.h
|
||||
xfree.o: xmalloc.h
|
||||
xmalloc.o: xmalloc.h
|
||||
colors.o: xmalloc.h
|
||||
parse-colors.o: xmalloc.h
|
||||
|
||||
complete.o: rlmbutil.h
|
||||
display.o: rlmbutil.h
|
||||
|
@ -332,6 +348,8 @@ readline.o: rlmbutil.h
|
|||
search.o: rlmbutil.h
|
||||
text.o: rlmbutil.h
|
||||
vi_mode.o: rlmbutil.h
|
||||
colors.o: rlmbutil.h
|
||||
parse-colors.o: rlmbutil.h
|
||||
|
||||
# Rules for deficient makes, like SunOS and Solaris
|
||||
bind.o: bind.c
|
||||
|
@ -364,6 +382,9 @@ vi_mode.o: vi_mode.c
|
|||
xfree.o: xfree.c
|
||||
xmalloc.o: xmalloc.c
|
||||
|
||||
colors.o: colors.c
|
||||
parse-colors.o: parse-colors.c
|
||||
|
||||
histexpand.o: histexpand.c
|
||||
histfile.o: histfile.c
|
||||
history.o: history.c
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* bind.c -- key binding and startup file support for the readline library. */
|
||||
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2012 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.
|
||||
|
@ -72,11 +72,15 @@ extern char *strchr (), *strrchr ();
|
|||
/* Variables exported by this file. */
|
||||
Keymap rl_binding_keymap;
|
||||
|
||||
static int _rl_skip_to_delim PARAMS((char *, int, int));
|
||||
|
||||
static char *_rl_read_file PARAMS((char *, size_t *));
|
||||
static void _rl_init_file_error PARAMS((const char *));
|
||||
static int _rl_read_init_file PARAMS((const char *, int));
|
||||
static int glean_key_from_name PARAMS((char *));
|
||||
|
||||
static int find_boolean_var PARAMS((const char *));
|
||||
static int find_string_var PARAMS((const char *));
|
||||
|
||||
static char *_rl_get_string_variable_value PARAMS((const char *));
|
||||
static int substring_member_of_array PARAMS((const char *, const char * const *));
|
||||
|
@ -567,6 +571,40 @@ rl_translate_keyseq (seq, array, len)
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
_rl_isescape (c)
|
||||
int c;
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\007':
|
||||
case '\b':
|
||||
case '\f':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case TAB:
|
||||
case 0x0b: return (1);
|
||||
default: return (0);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_rl_escchar (c)
|
||||
int c;
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\007': return ('a');
|
||||
case '\b': return ('b');
|
||||
case '\f': return ('f');
|
||||
case '\n': return ('n');
|
||||
case '\r': return ('r');
|
||||
case TAB: return ('t');
|
||||
case 0x0b: return ('v');
|
||||
default: return (c);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
rl_untranslate_keyseq (seq)
|
||||
int seq;
|
||||
|
@ -618,9 +656,10 @@ rl_untranslate_keyseq (seq)
|
|||
return kseq;
|
||||
}
|
||||
|
||||
static char *
|
||||
_rl_untranslate_macro_value (seq)
|
||||
char *
|
||||
_rl_untranslate_macro_value (seq, use_escapes)
|
||||
char *seq;
|
||||
int use_escapes;
|
||||
{
|
||||
char *ret, *r, *s;
|
||||
int c;
|
||||
|
@ -644,9 +683,14 @@ _rl_untranslate_macro_value (seq)
|
|||
else if (CTRL_CHAR (c))
|
||||
{
|
||||
*r++ = '\\';
|
||||
*r++ = 'C';
|
||||
*r++ = '-';
|
||||
c = _rl_to_lower (UNCTRL (c));
|
||||
if (use_escapes && _rl_isescape (c))
|
||||
c = _rl_escchar (c);
|
||||
else
|
||||
{
|
||||
*r++ = 'C';
|
||||
*r++ = '-';
|
||||
c = _rl_to_lower (UNCTRL (c));
|
||||
}
|
||||
}
|
||||
else if (c == RUBOUT)
|
||||
{
|
||||
|
@ -1157,6 +1201,38 @@ handle_parser_directive (statement)
|
|||
return (1);
|
||||
}
|
||||
|
||||
/* Start at STRING[START] and look for DELIM. Return I where STRING[I] ==
|
||||
DELIM or STRING[I] == 0. DELIM is usually a double quote. */
|
||||
static int
|
||||
_rl_skip_to_delim (string, start, delim)
|
||||
char *string;
|
||||
int start, delim;
|
||||
{
|
||||
int i, c, passc;
|
||||
|
||||
for (i = start,passc = 0; c = string[i]; i++)
|
||||
{
|
||||
if (passc)
|
||||
{
|
||||
passc = 0;
|
||||
if (c == 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\\')
|
||||
{
|
||||
passc = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == delim)
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Read the binding command from STRING and perform it.
|
||||
A key binding command looks like: Keyname: function-name\0,
|
||||
a variable binding command looks like: set variable value.
|
||||
|
@ -1172,7 +1248,7 @@ rl_parse_and_bind (string)
|
|||
while (string && whitespace (*string))
|
||||
string++;
|
||||
|
||||
if (!string || !*string || *string == '#')
|
||||
if (string == 0 || *string == 0 || *string == '#')
|
||||
return 0;
|
||||
|
||||
/* If this is a parser directive, act on it. */
|
||||
|
@ -1192,31 +1268,16 @@ rl_parse_and_bind (string)
|
|||
backslash to quote characters in the key expression. */
|
||||
if (*string == '"')
|
||||
{
|
||||
int passc = 0;
|
||||
i = _rl_skip_to_delim (string, 1, '"');
|
||||
|
||||
for (i = 1; c = string[i]; i++)
|
||||
{
|
||||
if (passc)
|
||||
{
|
||||
passc = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\\')
|
||||
{
|
||||
passc++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '"')
|
||||
break;
|
||||
}
|
||||
/* If we didn't find a closing quote, abort the line. */
|
||||
if (string[i] == '\0')
|
||||
{
|
||||
_rl_init_file_error ("no closing `\"' in key binding");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
i++; /* skip past closing double quote */
|
||||
}
|
||||
|
||||
/* Advance to the colon (:) or whitespace which separates the two objects. */
|
||||
|
@ -1236,6 +1297,7 @@ rl_parse_and_bind (string)
|
|||
if (_rl_stricmp (string, "set") == 0)
|
||||
{
|
||||
char *var, *value, *e;
|
||||
int s;
|
||||
|
||||
var = string + i;
|
||||
/* Make VAR point to start of variable name. */
|
||||
|
@ -1243,25 +1305,37 @@ rl_parse_and_bind (string)
|
|||
|
||||
/* Make VALUE point to start of value string. */
|
||||
value = var;
|
||||
while (*value && !whitespace (*value)) value++;
|
||||
while (*value && whitespace (*value) == 0) value++;
|
||||
if (*value)
|
||||
*value++ = '\0';
|
||||
while (*value && whitespace (*value)) value++;
|
||||
|
||||
/* Strip trailing whitespace from values to boolean variables. Temp
|
||||
fix until I get a real quoted-string parser here. */
|
||||
i = find_boolean_var (var);
|
||||
if (i >= 0)
|
||||
/* Strip trailing whitespace from values of boolean variables. */
|
||||
if (find_boolean_var (var) >= 0)
|
||||
{
|
||||
/* remove trailing whitespace */
|
||||
remove_trailing:
|
||||
e = value + strlen (value) - 1;
|
||||
while (e >= value && whitespace (*e))
|
||||
e--;
|
||||
e++; /* skip back to whitespace or EOS */
|
||||
|
||||
if (*e && e >= value)
|
||||
*e = '\0';
|
||||
}
|
||||
|
||||
else if ((i = find_string_var (var)) >= 0)
|
||||
{
|
||||
/* Allow quoted strings in variable values */
|
||||
if (*value == '"')
|
||||
{
|
||||
i = _rl_skip_to_delim (value, 1, *value);
|
||||
value[i] = '\0';
|
||||
value++; /* skip past the quote */
|
||||
}
|
||||
else
|
||||
goto remove_trailing;
|
||||
}
|
||||
|
||||
rl_variable_bind (var, value);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1282,32 +1356,13 @@ rl_parse_and_bind (string)
|
|||
the quoted string delimiter, like the shell. */
|
||||
if (*funname == '\'' || *funname == '"')
|
||||
{
|
||||
int delimiter, passc;
|
||||
|
||||
delimiter = string[i++];
|
||||
for (passc = 0; c = string[i]; i++)
|
||||
{
|
||||
if (passc)
|
||||
{
|
||||
passc = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\\')
|
||||
{
|
||||
passc = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == delimiter)
|
||||
break;
|
||||
}
|
||||
if (c)
|
||||
i = _rl_skip_to_delim (string, i+1, *funname);
|
||||
if (string[i])
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Advance to the end of the string. */
|
||||
for (; string[i] && !whitespace (string[i]); i++);
|
||||
for (; string[i] && whitespace (string[i]) == 0; i++);
|
||||
|
||||
/* No extra whitespace at the end of the string. */
|
||||
string[i] = '\0';
|
||||
|
@ -1367,7 +1422,7 @@ rl_parse_and_bind (string)
|
|||
|
||||
/* Get the actual character we want to deal with. */
|
||||
kname = strrchr (string, '-');
|
||||
if (!kname)
|
||||
if (kname == 0)
|
||||
kname = string;
|
||||
else
|
||||
kname++;
|
||||
|
@ -1423,6 +1478,9 @@ static const struct {
|
|||
{ "bind-tty-special-chars", &_rl_bind_stty_chars, 0 },
|
||||
{ "blink-matching-paren", &rl_blink_matching_paren, V_SPECIAL },
|
||||
{ "byte-oriented", &rl_byte_oriented, 0 },
|
||||
#if defined (COLOR_SUPPORT)
|
||||
{ "colored-stats", &_rl_colored_stats, 0 },
|
||||
#endif
|
||||
{ "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 },
|
||||
|
@ -1447,6 +1505,7 @@ static const struct {
|
|||
{ "revert-all-at-newline", &_rl_revert_all_at_newline, 0 },
|
||||
{ "show-all-if-ambiguous", &_rl_complete_show_all, 0 },
|
||||
{ "show-all-if-unmodified", &_rl_complete_show_unmodified, 0 },
|
||||
{ "show-mode-in-prompt", &_rl_show_mode_in_prompt, 0 },
|
||||
{ "skip-completed-text", &_rl_skip_completed_text, 0 },
|
||||
#if defined (VISIBLE_STATS)
|
||||
{ "visible-stats", &rl_visible_stats, 0 },
|
||||
|
@ -1486,6 +1545,8 @@ hack_special_boolean_var (i)
|
|||
else
|
||||
_rl_bell_preference = AUDIBLE_BELL;
|
||||
}
|
||||
else if (_rl_stricmp (name, "show-mode-in-prompt") == 0)
|
||||
_rl_reset_prompt ();
|
||||
}
|
||||
|
||||
typedef int _rl_sv_func_t PARAMS((const char *));
|
||||
|
@ -1511,6 +1572,7 @@ static int sv_editmode PARAMS((const char *));
|
|||
static int sv_histsize PARAMS((const char *));
|
||||
static int sv_isrchterm PARAMS((const char *));
|
||||
static int sv_keymap PARAMS((const char *));
|
||||
static int sv_seqtimeout PARAMS((const char *));
|
||||
|
||||
static const struct {
|
||||
const char * const name;
|
||||
|
@ -1526,6 +1588,7 @@ static const struct {
|
|||
{ "history-size", V_INT, sv_histsize },
|
||||
{ "isearch-terminators", V_STRING, sv_isrchterm },
|
||||
{ "keymap", V_STRING, sv_keymap },
|
||||
{ "keyseq-timeout", V_INT, sv_seqtimeout },
|
||||
{ (char *)NULL, 0, (_rl_sv_func_t *)0 }
|
||||
};
|
||||
|
||||
|
@ -1683,13 +1746,17 @@ static int
|
|||
sv_histsize (value)
|
||||
const char *value;
|
||||
{
|
||||
int nval = 500;
|
||||
int nval;
|
||||
|
||||
nval = 500;
|
||||
if (value && *value)
|
||||
{
|
||||
nval = atoi (value);
|
||||
if (nval < 0)
|
||||
return 1;
|
||||
{
|
||||
unstifle_history ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
stifle_history (nval);
|
||||
return 0;
|
||||
|
@ -1710,6 +1777,23 @@ sv_keymap (value)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
sv_seqtimeout (value)
|
||||
const char *value;
|
||||
{
|
||||
int nval;
|
||||
|
||||
nval = 0;
|
||||
if (value && *value)
|
||||
{
|
||||
nval = atoi (value);
|
||||
if (nval < 0)
|
||||
nval = 0;
|
||||
}
|
||||
_rl_keyseq_timeout = nval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sv_bell_style (value)
|
||||
const char *value;
|
||||
|
@ -2167,6 +2251,8 @@ rl_function_dumper (print_readably)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
xfree (names);
|
||||
}
|
||||
|
||||
/* Print all of the current functions and their bindings to
|
||||
|
@ -2199,7 +2285,7 @@ _rl_macro_dumper_internal (print_readably, map, prefix)
|
|||
{
|
||||
case ISMACR:
|
||||
keyname = _rl_get_keyname (key);
|
||||
out = _rl_untranslate_macro_value ((char *)map[key].function);
|
||||
out = _rl_untranslate_macro_value ((char *)map[key].function, 0);
|
||||
|
||||
if (print_readably)
|
||||
fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
|
||||
|
@ -2311,7 +2397,7 @@ _rl_get_string_variable_value (name)
|
|||
{
|
||||
if (_rl_isearch_terminators == 0)
|
||||
return 0;
|
||||
ret = _rl_untranslate_macro_value (_rl_isearch_terminators);
|
||||
ret = _rl_untranslate_macro_value (_rl_isearch_terminators, 0);
|
||||
if (ret)
|
||||
{
|
||||
strncpy (numbuf, ret, sizeof (numbuf) - 1);
|
||||
|
@ -2329,6 +2415,11 @@ _rl_get_string_variable_value (name)
|
|||
ret = rl_get_keymap_name_from_edit_mode ();
|
||||
return (ret ? ret : "none");
|
||||
}
|
||||
else if (_rl_stricmp (name, "keyseq-timeout") == 0)
|
||||
{
|
||||
sprintf (numbuf, "%d", _rl_keyseq_timeout);
|
||||
return (numbuf);
|
||||
}
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -62,8 +62,10 @@ _rl_callback_generic_arg *_rl_callback_data = 0;
|
|||
whenever a complete line of input is ready. The user must then
|
||||
call rl_callback_read_char() every time some input is available, and
|
||||
rl_callback_read_char() will call the user's function with the complete
|
||||
text read in at each end of line. The terminal is kept prepped and
|
||||
signals handled all the time, except during calls to the user's function. */
|
||||
text read in at each end of line. The terminal is kept prepped
|
||||
all the time, except during calls to the user's function. Signal
|
||||
handlers are only installed when the application calls back into
|
||||
readline, so readline doesn't `steal' signals from the application. */
|
||||
|
||||
rl_vcpfunc_t *rl_linefunc; /* user callback function */
|
||||
static int in_handler; /* terminal_prepped and signals set? */
|
||||
|
@ -80,10 +82,6 @@ _rl_callback_newline ()
|
|||
|
||||
if (rl_prep_term_function)
|
||||
(*rl_prep_term_function) (_rl_meta_flag);
|
||||
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
rl_set_signals ();
|
||||
#endif
|
||||
}
|
||||
|
||||
readline_internal_setup ();
|
||||
|
@ -102,6 +100,16 @@ rl_callback_handler_install (prompt, linefunc)
|
|||
_rl_callback_newline ();
|
||||
}
|
||||
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
#define CALLBACK_READ_RETURN() \
|
||||
do { \
|
||||
rl_clear_signals (); \
|
||||
return; \
|
||||
} while (0)
|
||||
#else
|
||||
#define CALLBACK_READ_RETURN() return
|
||||
#endif
|
||||
|
||||
/* Read one character, and dispatch to the handler if it ends the line. */
|
||||
void
|
||||
rl_callback_read_char ()
|
||||
|
@ -117,15 +125,24 @@ rl_callback_read_char ()
|
|||
}
|
||||
|
||||
memcpy ((void *)olevel, (void *)_rl_top_level, sizeof (procenv_t));
|
||||
#if defined (HAVE_POSIX_SIGSETJMP)
|
||||
jcode = sigsetjmp (_rl_top_level, 0);
|
||||
#else
|
||||
jcode = setjmp (_rl_top_level);
|
||||
#endif
|
||||
if (jcode)
|
||||
{
|
||||
(*rl_redisplay_function) ();
|
||||
_rl_want_redisplay = 0;
|
||||
memcpy ((void *)_rl_top_level, (void *)olevel, sizeof (procenv_t));
|
||||
return;
|
||||
CALLBACK_READ_RETURN ();
|
||||
}
|
||||
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
/* Install signal handlers only when readline has control. */
|
||||
rl_set_signals ();
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
RL_CHECK_SIGNALS ();
|
||||
|
@ -135,12 +152,13 @@ rl_callback_read_char ()
|
|||
if (eof == 0 && (RL_ISSTATE (RL_STATE_ISEARCH) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING))
|
||||
rl_callback_read_char ();
|
||||
|
||||
return;
|
||||
CALLBACK_READ_RETURN ();
|
||||
}
|
||||
else if (RL_ISSTATE (RL_STATE_NSEARCH))
|
||||
{
|
||||
eof = _rl_nsearch_callback (_rl_nscxt);
|
||||
return;
|
||||
|
||||
CALLBACK_READ_RETURN ();
|
||||
}
|
||||
#if defined (VI_MODE)
|
||||
else if (RL_ISSTATE (RL_STATE_VIMOTION))
|
||||
|
@ -151,7 +169,7 @@ rl_callback_read_char ()
|
|||
if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
|
||||
_rl_internal_char_cleanup ();
|
||||
|
||||
return;
|
||||
CALLBACK_READ_RETURN ();
|
||||
}
|
||||
#endif
|
||||
else if (RL_ISSTATE (RL_STATE_NUMERICARG))
|
||||
|
@ -163,7 +181,7 @@ rl_callback_read_char ()
|
|||
else if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
|
||||
_rl_internal_char_cleanup ();
|
||||
|
||||
return;
|
||||
CALLBACK_READ_RETURN ();
|
||||
}
|
||||
else if (RL_ISSTATE (RL_STATE_MULTIKEY))
|
||||
{
|
||||
|
@ -180,7 +198,7 @@ rl_callback_read_char ()
|
|||
{
|
||||
/* This allows functions that simply need to read an additional
|
||||
character (like quoted-insert) to register a function to be
|
||||
called when input is available. _rl_callback_data is simply a
|
||||
called when input is available. _rl_callback_data is a
|
||||
pointer to a struct that has the argument count originally
|
||||
passed to the registering function and space for any additional
|
||||
parameters. */
|
||||
|
@ -230,6 +248,8 @@ rl_callback_read_char ()
|
|||
}
|
||||
}
|
||||
while (rl_pending_input || _rl_pushed_input_available () || RL_ISSTATE (RL_STATE_MACROINPUT));
|
||||
|
||||
CALLBACK_READ_RETURN ();
|
||||
}
|
||||
|
||||
/* Remove the handler, and make sure the terminal is in its normal state. */
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
# define IN_CTYPE_DOMAIN(c) isascii(c)
|
||||
#endif
|
||||
|
||||
#if !defined (isxdigit) && !defined (HAVE_ISXDIGIT)
|
||||
#if !defined (isxdigit) && !defined (HAVE_ISXDIGIT) && !defined (__cplusplus)
|
||||
# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
|
||||
#endif
|
||||
|
||||
|
|
251
lib/readline/colors.c
Normal file
251
lib/readline/colors.c
Normal file
|
@ -0,0 +1,251 @@
|
|||
/* `dir', `vdir' and `ls' directory listing programs for GNU.
|
||||
|
||||
Modified by Chet Ramey for Readline.
|
||||
|
||||
Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 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/>. */
|
||||
|
||||
/* Written by Richard Stallman and David MacKenzie. */
|
||||
|
||||
/* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis
|
||||
Flaherty <dennisf@denix.elk.miles.com> based on original patches by
|
||||
Greg Lee <lee@uhunix.uhcc.hawaii.edu>. */
|
||||
|
||||
#define READLINE_LIBRARY
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "rlconf.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "posixstat.h" // stat related macros (S_ISREG, ...)
|
||||
#include <fcntl.h> // S_ISUID
|
||||
|
||||
// strlen()
|
||||
#if defined (HAVE_STRING_H)
|
||||
# include <string.h>
|
||||
#else /* !HAVE_STRING_H */
|
||||
# include <strings.h>
|
||||
#endif /* !HAVE_STRING_H */
|
||||
|
||||
// abort()
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#include "readline.h"
|
||||
#include "rldefs.h"
|
||||
|
||||
#ifdef COLOR_SUPPORT
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "colors.h"
|
||||
|
||||
static bool is_colored (enum indicator_no type);
|
||||
static void restore_default_color (void);
|
||||
|
||||
COLOR_EXT_TYPE *_rl_color_ext_list = 0;
|
||||
|
||||
/* Output a color indicator (which may contain nulls). */
|
||||
void
|
||||
_rl_put_indicator (const struct bin_str *ind) {
|
||||
fwrite (ind->string, ind->len, 1, rl_outstream);
|
||||
}
|
||||
|
||||
static bool
|
||||
is_colored (enum indicator_no colored_filetype)
|
||||
{
|
||||
size_t len = _rl_color_indicator[colored_filetype].len;
|
||||
char const *s = _rl_color_indicator[colored_filetype].string;
|
||||
return ! (len == 0
|
||||
|| (len == 1 && strncmp (s, "0", 1) == 0)
|
||||
|| (len == 2 && strncmp (s, "00", 2) == 0));
|
||||
}
|
||||
|
||||
static void
|
||||
restore_default_color (void)
|
||||
{
|
||||
_rl_put_indicator (&_rl_color_indicator[C_LEFT]);
|
||||
_rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
|
||||
}
|
||||
|
||||
void
|
||||
_rl_set_normal_color (void)
|
||||
{
|
||||
if (is_colored (C_NORM))
|
||||
{
|
||||
_rl_put_indicator (&_rl_color_indicator[C_LEFT]);
|
||||
_rl_put_indicator (&_rl_color_indicator[C_NORM]);
|
||||
_rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns whether any color sequence was printed. */
|
||||
bool
|
||||
_rl_print_color_indicator (char *f)
|
||||
{
|
||||
enum indicator_no colored_filetype;
|
||||
COLOR_EXT_TYPE *ext; /* Color extension */
|
||||
size_t len; /* Length of name */
|
||||
|
||||
const char* name;
|
||||
char *filename;
|
||||
struct stat astat;
|
||||
mode_t mode;
|
||||
int linkok;
|
||||
|
||||
int stat_ok;
|
||||
|
||||
name = f;
|
||||
|
||||
/* This should already have undergone tilde expansion */
|
||||
filename = 0;
|
||||
if (rl_filename_stat_hook)
|
||||
{
|
||||
filename = savestring (f);
|
||||
(*rl_filename_stat_hook) (&filename);
|
||||
name = filename;
|
||||
}
|
||||
|
||||
#if defined (HAVE_LSTAT)
|
||||
stat_ok = lstat(name, &astat);
|
||||
#else
|
||||
stat_ok = stat(name, &astat);
|
||||
#endif
|
||||
if( stat_ok == 0 ) {
|
||||
mode = astat.st_mode;
|
||||
linkok = 1; //f->linkok;
|
||||
}
|
||||
else
|
||||
linkok = -1;
|
||||
|
||||
/* Is this a nonexistent file? If so, linkok == -1. */
|
||||
|
||||
if (linkok == -1 && _rl_color_indicator[C_MISSING].string != NULL)
|
||||
colored_filetype = C_MISSING;
|
||||
else if(stat_ok != 0)
|
||||
{
|
||||
static enum indicator_no filetype_indicator[] = FILETYPE_INDICATORS;
|
||||
colored_filetype = filetype_indicator[normal]; //f->filetype];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (S_ISREG (mode))
|
||||
{
|
||||
colored_filetype = C_FILE;
|
||||
|
||||
if ((mode & S_ISUID) != 0 && is_colored (C_SETUID))
|
||||
colored_filetype = C_SETUID;
|
||||
else if ((mode & S_ISGID) != 0 && is_colored (C_SETGID))
|
||||
colored_filetype = C_SETGID;
|
||||
else if (is_colored (C_CAP) && 0) //f->has_capability)
|
||||
colored_filetype = C_CAP;
|
||||
else if ((mode & S_IXUGO) != 0 && is_colored (C_EXEC))
|
||||
colored_filetype = C_EXEC;
|
||||
else if ((1 < astat.st_nlink) && is_colored (C_MULTIHARDLINK))
|
||||
colored_filetype = C_MULTIHARDLINK;
|
||||
}
|
||||
else if (S_ISDIR (mode))
|
||||
{
|
||||
colored_filetype = C_DIR;
|
||||
|
||||
#if defined (S_ISVTX)
|
||||
if ((mode & S_ISVTX) && (mode & S_IWOTH)
|
||||
&& is_colored (C_STICKY_OTHER_WRITABLE))
|
||||
colored_filetype = C_STICKY_OTHER_WRITABLE;
|
||||
else
|
||||
#endif
|
||||
if ((mode & S_IWOTH) != 0 && is_colored (C_OTHER_WRITABLE))
|
||||
colored_filetype = C_OTHER_WRITABLE;
|
||||
#if defined (S_ISVTX)
|
||||
else if ((mode & S_ISVTX) != 0 && is_colored (C_STICKY))
|
||||
colored_filetype = C_STICKY;
|
||||
#endif
|
||||
}
|
||||
else if (S_ISLNK (mode))
|
||||
colored_filetype = ((linkok == 0
|
||||
&& (!strncmp (_rl_color_indicator[C_LINK].string, "target", 6)
|
||||
|| _rl_color_indicator[C_ORPHAN].string))
|
||||
? C_ORPHAN : C_LINK);
|
||||
else if (S_ISFIFO (mode))
|
||||
colored_filetype = C_FIFO;
|
||||
else if (S_ISSOCK (mode))
|
||||
colored_filetype = C_SOCK;
|
||||
else if (S_ISBLK (mode))
|
||||
colored_filetype = C_BLK;
|
||||
else if (S_ISCHR (mode))
|
||||
colored_filetype = C_CHR;
|
||||
else
|
||||
{
|
||||
/* Classify a file of some other type as C_ORPHAN. */
|
||||
colored_filetype = C_ORPHAN;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the file's suffix only if still classified as C_FILE. */
|
||||
ext = NULL;
|
||||
if (colored_filetype == C_FILE)
|
||||
{
|
||||
/* Test if NAME has a recognized suffix. */
|
||||
len = strlen (name);
|
||||
name += len; /* Pointer to final \0. */
|
||||
for (ext = _rl_color_ext_list; ext != NULL; ext = ext->next)
|
||||
{
|
||||
if (ext->ext.len <= len
|
||||
&& strncmp (name - ext->ext.len, ext->ext.string,
|
||||
ext->ext.len) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (filename); /* NULL or savestring return value */
|
||||
|
||||
{
|
||||
const struct bin_str *const s
|
||||
= ext ? &(ext->seq) : &_rl_color_indicator[colored_filetype];
|
||||
if (s->string != NULL)
|
||||
{
|
||||
/* Need to reset so not dealing with attribute combinations */
|
||||
if (is_colored (C_NORM))
|
||||
restore_default_color ();
|
||||
_rl_put_indicator (&_rl_color_indicator[C_LEFT]);
|
||||
_rl_put_indicator (s);
|
||||
_rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_rl_prep_non_filename_text (void)
|
||||
{
|
||||
if (_rl_color_indicator[C_END].string != NULL)
|
||||
_rl_put_indicator (&_rl_color_indicator[C_END]);
|
||||
else
|
||||
{
|
||||
_rl_put_indicator (&_rl_color_indicator[C_LEFT]);
|
||||
_rl_put_indicator (&_rl_color_indicator[C_RESET]);
|
||||
_rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
|
||||
}
|
||||
}
|
||||
#endif /* COLOR_SUPPORT */
|
122
lib/readline/colors.h
Normal file
122
lib/readline/colors.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
/* `dir', `vdir' and `ls' directory listing programs for GNU.
|
||||
|
||||
Modified by Chet Ramey for Readline.
|
||||
|
||||
Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 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/>. */
|
||||
|
||||
/* Written by Richard Stallman and David MacKenzie. */
|
||||
|
||||
/* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis
|
||||
Flaherty <dennisf@denix.elk.miles.com> based on original patches by
|
||||
Greg Lee <lee@uhunix.uhcc.hawaii.edu>. */
|
||||
|
||||
#ifndef _COLORS_H_
|
||||
#define _COLORS_H_
|
||||
|
||||
#include <stdio.h> // size_t
|
||||
|
||||
#if defined(__TANDEM) && defined(HAVE_STDBOOL_H) && (__STDC_VERSION__ < 199901L)
|
||||
typedef int _Bool;
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_STDBOOL_H)
|
||||
# include <stdbool.h> // bool
|
||||
#else
|
||||
typedef int _rl_bool_t;
|
||||
|
||||
#ifdef bool
|
||||
# undef bool
|
||||
#endif
|
||||
#define bool _rl_bool_t
|
||||
|
||||
#ifndef true
|
||||
# define true 1
|
||||
# define false 0
|
||||
#endif
|
||||
|
||||
#endif /* !HAVE_STDBOOL_H */
|
||||
|
||||
/* Null is a valid character in a color indicator (think about Epson
|
||||
printers, for example) so we have to use a length/buffer string
|
||||
type. */
|
||||
struct bin_str
|
||||
{
|
||||
size_t len;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
/* file type indicators (dir, sock, fifo, ...)
|
||||
Default value is initialized in parse-colors.c.
|
||||
It is then modified from the values of $LS_COLORS. */
|
||||
extern struct bin_str _rl_color_indicator[];
|
||||
|
||||
/* The LS_COLORS variable is in a termcap-like format. */
|
||||
typedef struct _color_ext_type
|
||||
{
|
||||
struct bin_str ext; /* The extension we're looking for */
|
||||
struct bin_str seq; /* The sequence to output when we do */
|
||||
struct _color_ext_type *next; /* Next in list */
|
||||
} COLOR_EXT_TYPE;
|
||||
|
||||
/* file extensions indicators (.txt, .log, .jpg, ...)
|
||||
Values are taken from $LS_COLORS in rl_parse_colors(). */
|
||||
extern COLOR_EXT_TYPE *_rl_color_ext_list;
|
||||
|
||||
#define FILETYPE_INDICATORS \
|
||||
{ \
|
||||
C_ORPHAN, C_FIFO, C_CHR, C_DIR, C_BLK, C_FILE, \
|
||||
C_LINK, C_SOCK, C_FILE, C_DIR \
|
||||
}
|
||||
|
||||
/* Whether we used any colors in the output so far. If so, we will
|
||||
need to restore the default color later. If not, we will need to
|
||||
call prep_non_filename_text before using color for the first time. */
|
||||
|
||||
enum indicator_no
|
||||
{
|
||||
C_LEFT, C_RIGHT, C_END, C_RESET, C_NORM, C_FILE, C_DIR, C_LINK,
|
||||
C_FIFO, C_SOCK,
|
||||
C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC, C_DOOR, C_SETUID, C_SETGID,
|
||||
C_STICKY, C_OTHER_WRITABLE, C_STICKY_OTHER_WRITABLE, C_CAP, C_MULTIHARDLINK,
|
||||
C_CLR_TO_EOL
|
||||
};
|
||||
|
||||
|
||||
#if !S_IXUGO
|
||||
# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
|
||||
#endif
|
||||
|
||||
enum filetype
|
||||
{
|
||||
unknown,
|
||||
fifo,
|
||||
chardev,
|
||||
directory,
|
||||
blockdev,
|
||||
normal,
|
||||
symbolic_link,
|
||||
sock,
|
||||
whiteout,
|
||||
arg_directory
|
||||
};
|
||||
|
||||
extern void _rl_put_indicator (const struct bin_str *ind);
|
||||
extern void _rl_set_normal_color (void);
|
||||
extern bool _rl_print_color_indicator (char *f);
|
||||
extern void _rl_prep_non_filename_text (void);
|
||||
|
||||
#endif /* !_COLORS_H_ */
|
|
@ -1,6 +1,6 @@
|
|||
/* complete.c -- filename completion for readline. */
|
||||
|
||||
/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2012 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.
|
||||
|
@ -31,6 +31,8 @@
|
|||
# include <sys/file.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
@ -64,6 +66,10 @@ extern int errno;
|
|||
#include "xmalloc.h"
|
||||
#include "rlprivate.h"
|
||||
|
||||
#if defined (COLOR_SUPPORT)
|
||||
# include "colors.h"
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef int QSFUNC (const void *, const void *);
|
||||
#else
|
||||
|
@ -94,17 +100,27 @@ extern struct passwd *getpwent PARAMS((void));
|
|||
longest string in that array. */
|
||||
rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL;
|
||||
|
||||
#if defined (VISIBLE_STATS)
|
||||
#if defined (VISIBLE_STATS) || defined (COLOR_SUPPORT)
|
||||
# if !defined (X_OK)
|
||||
# define X_OK 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (VISIBLE_STATS)
|
||||
static int stat_char PARAMS((char *));
|
||||
#endif
|
||||
|
||||
#if defined (COLOR_SUPPORT)
|
||||
static int colored_stat_start PARAMS((char *));
|
||||
static void colored_stat_end PARAMS((void));
|
||||
#endif
|
||||
|
||||
static int path_isdir PARAMS((const char *));
|
||||
|
||||
static char *rl_quote_filename PARAMS((char *, int, char *));
|
||||
|
||||
static void _rl_complete_sigcleanup PARAMS((int, void *));
|
||||
|
||||
static void set_completion_defaults PARAMS((int));
|
||||
static int get_y_or_n PARAMS((int));
|
||||
static int _rl_internal_pager PARAMS((int));
|
||||
|
@ -189,6 +205,12 @@ int _rl_completion_columns = -1;
|
|||
int rl_visible_stats = 0;
|
||||
#endif /* VISIBLE_STATS */
|
||||
|
||||
#if defined (COLOR_SUPPORT)
|
||||
/* Non-zero means to use colors to indicate file type when listing possible
|
||||
completions. The colors used are taken from $LS_COLORS, if set. */
|
||||
int _rl_colored_stats = 0;
|
||||
#endif
|
||||
|
||||
/* If non-zero, when completing in the middle of a word, don't insert
|
||||
characters from the match that match characters following point in
|
||||
the word. This means, for instance, completing when the cursor is
|
||||
|
@ -206,6 +228,8 @@ rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
|
|||
|
||||
rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
|
||||
|
||||
rl_icppfunc_t *rl_filename_stat_hook = (rl_icppfunc_t *)NULL;
|
||||
|
||||
/* If non-zero, this is the address of a function to call when reading
|
||||
directory entries from the filesystem for completion and comparing
|
||||
them to the partial word to be completed. The function should
|
||||
|
@ -457,6 +481,15 @@ _rl_reset_completion_state ()
|
|||
rl_completion_quote_character = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_rl_complete_sigcleanup (sig, ptr)
|
||||
int sig;
|
||||
void *ptr;
|
||||
{
|
||||
if (sig == SIGINT) /* XXX - for now */
|
||||
_rl_free_match_list ((char **)ptr);
|
||||
}
|
||||
|
||||
/* Set default values for readline word completion. These are the variables
|
||||
that application completion functions can change or inspect. */
|
||||
static void
|
||||
|
@ -551,6 +584,8 @@ stat_char (filename)
|
|||
{
|
||||
struct stat finfo;
|
||||
int character, r;
|
||||
char *f;
|
||||
const char *fn;
|
||||
|
||||
/* Short-circuit a //server on cygwin, since that will always behave as
|
||||
a directory. */
|
||||
|
@ -559,10 +594,20 @@ stat_char (filename)
|
|||
return '/';
|
||||
#endif
|
||||
|
||||
f = 0;
|
||||
if (rl_filename_stat_hook)
|
||||
{
|
||||
f = savestring (filename);
|
||||
(*rl_filename_stat_hook) (&f);
|
||||
fn = f;
|
||||
}
|
||||
else
|
||||
fn = filename;
|
||||
|
||||
#if defined (HAVE_LSTAT) && defined (S_ISLNK)
|
||||
r = lstat (filename, &finfo);
|
||||
r = lstat (fn, &finfo);
|
||||
#else
|
||||
r = stat (filename, &finfo);
|
||||
r = stat (fn, &finfo);
|
||||
#endif
|
||||
|
||||
if (r == -1)
|
||||
|
@ -596,10 +641,29 @@ stat_char (filename)
|
|||
if (access (filename, X_OK) == 0)
|
||||
character = '*';
|
||||
}
|
||||
|
||||
free (f);
|
||||
return (character);
|
||||
}
|
||||
#endif /* VISIBLE_STATS */
|
||||
|
||||
#if defined (COLOR_SUPPORT)
|
||||
static int
|
||||
colored_stat_start (filename)
|
||||
char *filename;
|
||||
{
|
||||
_rl_set_normal_color ();
|
||||
return (_rl_print_color_indicator (filename));
|
||||
}
|
||||
|
||||
static void
|
||||
colored_stat_end ()
|
||||
{
|
||||
_rl_prep_non_filename_text ();
|
||||
_rl_put_indicator (&_rl_color_indicator[C_CLR_TO_EOL]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return the portion of PATHNAME that should be output when listing
|
||||
possible completions. If we are hacking filename completion, we
|
||||
are only interested in the basename, the portion following the
|
||||
|
@ -679,7 +743,7 @@ fnwidth (string)
|
|||
else
|
||||
{
|
||||
pos += clen;
|
||||
w = wcwidth (wc);
|
||||
w = WCWIDTH (wc);
|
||||
width += (w >= 0) ? w : 1;
|
||||
}
|
||||
#else
|
||||
|
@ -766,7 +830,7 @@ fnprint (to_print, prefix_bytes)
|
|||
break;
|
||||
else
|
||||
{
|
||||
w = wcwidth (wc);
|
||||
w = WCWIDTH (wc);
|
||||
width = (w >= 0) ? w : 1;
|
||||
}
|
||||
fwrite (s, 1, tlen, rl_outstream);
|
||||
|
@ -796,13 +860,20 @@ print_filename (to_print, full_pathname, prefix_bytes)
|
|||
char *s, c, *new_full_pathname, *dn;
|
||||
|
||||
extension_char = 0;
|
||||
printed_len = fnprint (to_print, prefix_bytes);
|
||||
|
||||
#if defined (VISIBLE_STATS)
|
||||
if (rl_filename_completion_desired && (rl_visible_stats || _rl_complete_mark_directories))
|
||||
#else
|
||||
if (rl_filename_completion_desired && _rl_complete_mark_directories)
|
||||
#if defined (COLOR_SUPPORT)
|
||||
/* Defer printing if we want to prefix with a color indicator */
|
||||
if (_rl_colored_stats == 0 || rl_filename_completion_desired == 0)
|
||||
#endif
|
||||
printed_len = fnprint (to_print, prefix_bytes);
|
||||
|
||||
if (rl_filename_completion_desired && (
|
||||
#if defined (VISIBLE_STATS)
|
||||
rl_visible_stats ||
|
||||
#endif
|
||||
#if defined (COLOR_SUPPORT)
|
||||
_rl_colored_stats ||
|
||||
#endif
|
||||
_rl_complete_mark_directories))
|
||||
{
|
||||
/* If to_print != full_pathname, to_print is the basename of the
|
||||
path passed. In this case, we try to expand the directory
|
||||
|
@ -848,8 +919,28 @@ print_filename (to_print, full_pathname, prefix_bytes)
|
|||
extension_char = stat_char (new_full_pathname);
|
||||
else
|
||||
#endif
|
||||
if (path_isdir (new_full_pathname))
|
||||
extension_char = '/';
|
||||
if (_rl_complete_mark_directories)
|
||||
{
|
||||
dn = 0;
|
||||
if (rl_directory_completion_hook == 0 && rl_filename_stat_hook)
|
||||
{
|
||||
dn = savestring (new_full_pathname);
|
||||
(*rl_filename_stat_hook) (&dn);
|
||||
free (new_full_pathname);
|
||||
new_full_pathname = dn;
|
||||
}
|
||||
if (path_isdir (new_full_pathname))
|
||||
extension_char = '/';
|
||||
}
|
||||
|
||||
#if defined (COLOR_SUPPORT)
|
||||
if (_rl_colored_stats)
|
||||
{
|
||||
colored_stat_start (new_full_pathname);
|
||||
printed_len = fnprint (to_print, prefix_bytes);
|
||||
colored_stat_end ();
|
||||
}
|
||||
#endif
|
||||
|
||||
xfree (new_full_pathname);
|
||||
to_print[-1] = c;
|
||||
|
@ -862,8 +953,18 @@ print_filename (to_print, full_pathname, prefix_bytes)
|
|||
extension_char = stat_char (s);
|
||||
else
|
||||
#endif
|
||||
if (path_isdir (s))
|
||||
if (_rl_complete_mark_directories && path_isdir (s))
|
||||
extension_char = '/';
|
||||
|
||||
#if defined (COLOR_SUPPORT)
|
||||
if (_rl_colored_stats)
|
||||
{
|
||||
colored_stat_start (s);
|
||||
printed_len = fnprint (to_print, prefix_bytes);
|
||||
colored_stat_end ();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
xfree (s);
|
||||
|
@ -1058,10 +1159,13 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
|
|||
variable rl_attempted_completion_function. */
|
||||
if (rl_attempted_completion_function)
|
||||
{
|
||||
_rl_interrupt_immediately++;
|
||||
matches = (*rl_attempted_completion_function) (text, start, end);
|
||||
if (_rl_interrupt_immediately > 0)
|
||||
_rl_interrupt_immediately--;
|
||||
if (RL_SIG_RECEIVED())
|
||||
{
|
||||
_rl_free_match_list (matches);
|
||||
matches = 0;
|
||||
RL_CHECK_SIGNALS ();
|
||||
}
|
||||
|
||||
if (matches || rl_attempted_completion_over)
|
||||
{
|
||||
|
@ -1072,7 +1176,15 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
|
|||
|
||||
/* XXX -- filename dequoting moved into rl_filename_completion_function */
|
||||
|
||||
/* rl_completion_matches will check for signals as well to avoid a long
|
||||
delay while reading a directory. */
|
||||
matches = rl_completion_matches (text, our_func);
|
||||
if (RL_SIG_RECEIVED())
|
||||
{
|
||||
_rl_free_match_list (matches);
|
||||
matches = 0;
|
||||
RL_CHECK_SIGNALS ();
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
|
@ -1147,9 +1259,11 @@ compute_lcd_of_matches (match_list, matches, text)
|
|||
{
|
||||
register int i, c1, c2, si;
|
||||
int low; /* Count of max-matched characters. */
|
||||
int lx;
|
||||
char *dtext; /* dequoted TEXT, if needed */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
int v;
|
||||
size_t v1, v2;
|
||||
mbstate_t ps1, ps2;
|
||||
wchar_t wc1, wc2;
|
||||
#endif
|
||||
|
@ -1182,14 +1296,20 @@ compute_lcd_of_matches (match_list, matches, text)
|
|||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
|
||||
mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
|
||||
v1 = mbrtowc(&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
|
||||
v2 = mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
|
||||
if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
|
||||
{
|
||||
if (c1 != c2) /* do byte comparison */
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
wc1 = towlower (wc1);
|
||||
wc2 = towlower (wc2);
|
||||
if (wc1 != wc2)
|
||||
break;
|
||||
else if (v > 1)
|
||||
si += v - 1;
|
||||
else if (v1 > 1)
|
||||
si += v1 - 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -1264,21 +1384,20 @@ compute_lcd_of_matches (match_list, matches, text)
|
|||
qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
|
||||
|
||||
si = strlen (text);
|
||||
if (si <= low)
|
||||
{
|
||||
for (i = 1; i <= matches; i++)
|
||||
if (strncmp (match_list[i], text, si) == 0)
|
||||
{
|
||||
strncpy (match_list[0], match_list[i], low);
|
||||
break;
|
||||
}
|
||||
/* no casematch, use first entry */
|
||||
if (i > matches)
|
||||
strncpy (match_list[0], match_list[1], low);
|
||||
}
|
||||
else
|
||||
/* otherwise, just use the text the user typed. */
|
||||
strncpy (match_list[0], text, low);
|
||||
lx = (si <= low) ? si : low; /* check shorter of text and matches */
|
||||
/* Try to preserve the case of what the user typed in the presence of
|
||||
multiple matches: check each match for something that matches
|
||||
what the user typed taking case into account; use it up to common
|
||||
length of matches if one is found. If not, just use first match. */
|
||||
for (i = 1; i <= matches; i++)
|
||||
if (strncmp (match_list[i], text, lx) == 0)
|
||||
{
|
||||
strncpy (match_list[0], match_list[i], low);
|
||||
break;
|
||||
}
|
||||
/* no casematch, use first entry */
|
||||
if (i > matches)
|
||||
strncpy (match_list[0], match_list[1], low);
|
||||
|
||||
FREE (dtext);
|
||||
}
|
||||
|
@ -1305,7 +1424,7 @@ postprocess_matches (matchesp, matching_filenames)
|
|||
return 0;
|
||||
|
||||
/* It seems to me that in all the cases we handle we would like
|
||||
to ignore duplicate possiblilities. Scan for the text to
|
||||
to ignore duplicate possibilities. Scan for the text to
|
||||
insert being identical to the other completions. */
|
||||
if (rl_ignore_completion_duplicates)
|
||||
{
|
||||
|
@ -1463,7 +1582,7 @@ rl_display_match_list (matches, len, max)
|
|||
/* Have we reached the end of this line? */
|
||||
if (matches[i+1])
|
||||
{
|
||||
if (i && (limit > 1) && (i % limit) == 0)
|
||||
if (limit == 1 || (i && (limit > 1) && (i % limit) == 0))
|
||||
{
|
||||
rl_crlf ();
|
||||
lines++;
|
||||
|
@ -1672,7 +1791,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
|
|||
char *text;
|
||||
int delimiter, quote_char, nontrivial_match;
|
||||
{
|
||||
char temp_string[4], *filename;
|
||||
char temp_string[4], *filename, *fn;
|
||||
int temp_string_index, s;
|
||||
struct stat finfo;
|
||||
|
||||
|
@ -1691,6 +1810,13 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
|
|||
if (rl_filename_completion_desired)
|
||||
{
|
||||
filename = tilde_expand (text);
|
||||
if (rl_filename_stat_hook)
|
||||
{
|
||||
fn = savestring (filename);
|
||||
(*rl_filename_stat_hook) (&fn);
|
||||
xfree (filename);
|
||||
filename = fn;
|
||||
}
|
||||
s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0)
|
||||
? LSTAT (filename, &finfo)
|
||||
: stat (filename, &finfo);
|
||||
|
@ -1710,8 +1836,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
|
|||
#ifdef S_ISLNK
|
||||
/* Don't add anything if the filename is a symlink and resolves to a
|
||||
directory. */
|
||||
else if (s == 0 && S_ISLNK (finfo.st_mode) &&
|
||||
stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode))
|
||||
else if (s == 0 && S_ISLNK (finfo.st_mode) && path_isdir (filename))
|
||||
;
|
||||
#endif
|
||||
else
|
||||
|
@ -1831,10 +1956,8 @@ 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;
|
||||
#if 1
|
||||
if (what_to_do == '!' || what_to_do == '@')
|
||||
tlen = strlen (text);
|
||||
#endif
|
||||
xfree (text);
|
||||
|
||||
if (matches == 0)
|
||||
|
@ -1868,10 +1991,6 @@ 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, "e_char);
|
||||
#else
|
||||
if (what_to_do == TAB)
|
||||
{
|
||||
if (*matches[0])
|
||||
|
@ -1886,7 +2005,6 @@ rl_complete_internal (what_to_do)
|
|||
if (mlen >= tlen)
|
||||
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_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.
|
||||
|
@ -1922,7 +2040,14 @@ rl_complete_internal (what_to_do)
|
|||
break;
|
||||
|
||||
case '?':
|
||||
if (rl_completion_display_matches_hook == 0)
|
||||
{
|
||||
_rl_sigcleanup = _rl_complete_sigcleanup;
|
||||
_rl_sigcleanarg = matches;
|
||||
}
|
||||
display_matches (matches);
|
||||
_rl_sigcleanup = 0;
|
||||
_rl_sigcleanarg = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1930,6 +2055,7 @@ rl_complete_internal (what_to_do)
|
|||
rl_ding ();
|
||||
FREE (saved_line_buffer);
|
||||
RL_UNSETSTATE(RL_STATE_COMPLETING);
|
||||
_rl_free_match_list (matches);
|
||||
_rl_reset_completion_state ();
|
||||
return 1;
|
||||
}
|
||||
|
@ -1971,6 +2097,8 @@ rl_completion_matches (text, entry_function)
|
|||
const char *text;
|
||||
rl_compentry_func_t *entry_function;
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* Number of slots in match_list. */
|
||||
int match_list_size;
|
||||
|
||||
|
@ -1988,18 +2116,36 @@ rl_completion_matches (text, entry_function)
|
|||
match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
|
||||
match_list[1] = (char *)NULL;
|
||||
|
||||
_rl_interrupt_immediately++;
|
||||
while (string = (*entry_function) (text, matches))
|
||||
{
|
||||
if (matches + 1 == match_list_size)
|
||||
if (RL_SIG_RECEIVED ())
|
||||
{
|
||||
/* Start at 1 because we don't set matches[0] in this function.
|
||||
Only free the list members if we're building match list from
|
||||
rl_filename_completion_function, since we know that doesn't
|
||||
free the strings it returns. */
|
||||
if (entry_function == rl_filename_completion_function)
|
||||
{
|
||||
for (i = 1; match_list[i]; i++)
|
||||
xfree (match_list[i]);
|
||||
}
|
||||
xfree (match_list);
|
||||
match_list = 0;
|
||||
match_list_size = 0;
|
||||
matches = 0;
|
||||
RL_CHECK_SIGNALS ();
|
||||
}
|
||||
|
||||
if (matches + 1 >= match_list_size)
|
||||
match_list = (char **)xrealloc
|
||||
(match_list, ((match_list_size += 10) + 1) * sizeof (char *));
|
||||
|
||||
if (match_list == 0)
|
||||
return (match_list);
|
||||
|
||||
match_list[++matches] = string;
|
||||
match_list[matches + 1] = (char *)NULL;
|
||||
}
|
||||
if (_rl_interrupt_immediately > 0)
|
||||
_rl_interrupt_immediately--;
|
||||
|
||||
/* If there were any matches, then look through them finding out the
|
||||
lowest common denominator. That then becomes match_list[0]. */
|
||||
|
@ -2038,7 +2184,9 @@ rl_username_completion_function (text, state)
|
|||
|
||||
username = savestring (&text[first_char_loc]);
|
||||
namelen = strlen (username);
|
||||
#if defined (HAVE_GETPWENT)
|
||||
setpwent ();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (HAVE_GETPWENT)
|
||||
|
@ -2075,8 +2223,9 @@ rl_username_completion_function (text, state)
|
|||
|
||||
/* 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. */
|
||||
regard to the alphabetic case of characters. If
|
||||
_rl_completion_case_map is set, make `-' and `_' equivalent. 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;
|
||||
|
@ -2086,34 +2235,110 @@ complete_fncmp (convfn, convlen, filename, filename_len)
|
|||
{
|
||||
register char *s1, *s2;
|
||||
int d, len;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
size_t v1, v2;
|
||||
mbstate_t ps1, ps2;
|
||||
wchar_t wc1, wc2;
|
||||
#endif
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
memset (&ps1, 0, sizeof (mbstate_t));
|
||||
memset (&ps2, 0, sizeof (mbstate_t));
|
||||
#endif
|
||||
|
||||
if (filename_len == 0)
|
||||
return 1;
|
||||
if (convlen < filename_len)
|
||||
return 0;
|
||||
|
||||
len = filename_len;
|
||||
s1 = (char *)convfn;
|
||||
s2 = (char *)filename;
|
||||
|
||||
/* 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
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
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 */
|
||||
do
|
||||
{
|
||||
v1 = mbrtowc (&wc1, s1, convlen, &ps1);
|
||||
v2 = mbrtowc (&wc2, s2, filename_len, &ps2);
|
||||
if (v1 == 0 && v2 == 0)
|
||||
return 1;
|
||||
else if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
|
||||
{
|
||||
if (*s1 != *s2) /* do byte comparison */
|
||||
return 0;
|
||||
else if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
|
||||
return 0;
|
||||
s1++; s2++; len--;
|
||||
continue;
|
||||
}
|
||||
wc1 = towlower (wc1);
|
||||
wc2 = towlower (wc2);
|
||||
s1 += v1;
|
||||
s2 += v1;
|
||||
len -= v1;
|
||||
if ((wc1 == L'-' || wc1 == L'_') && (wc2 == L'-' || wc2 == L'_'))
|
||||
continue;
|
||||
if (wc1 != wc2)
|
||||
return 0;
|
||||
}
|
||||
while (len != 0);
|
||||
}
|
||||
while (--len != 0);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
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 defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
v1 = mbrtowc (&wc1, s1, convlen, &ps1);
|
||||
v2 = mbrtowc (&wc2, s2, filename_len, &ps2);
|
||||
if (v1 == 0 && v2 == 0)
|
||||
return 1;
|
||||
else if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
|
||||
{
|
||||
if (*s1 != *s2) /* do byte comparison */
|
||||
return 0;
|
||||
s1++; s2++; len--;
|
||||
continue;
|
||||
}
|
||||
wc1 = towlower (wc1);
|
||||
wc2 = towlower (wc2);
|
||||
if (wc1 != wc2)
|
||||
return 0;
|
||||
s1 += v1;
|
||||
s2 += v1;
|
||||
len -= v1;
|
||||
}
|
||||
while (len != 0);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
|
||||
(convlen >= filename_len) &&
|
||||
(_rl_strnicmp (filename, convfn, filename_len) == 0))
|
||||
|
@ -2233,8 +2458,9 @@ rl_filename_completion_function (text, state)
|
|||
}
|
||||
directory = opendir (dirname);
|
||||
|
||||
/* Now dequote a non-null filename. */
|
||||
if (filename && *filename && rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
/* Now dequote a non-null filename. FILENAME will not be NULL, but may
|
||||
be empty. */
|
||||
if (*filename && rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
{
|
||||
/* delete single and double quotes */
|
||||
temp = (*rl_filename_dequoting_function) (filename, rl_completion_quote_character);
|
||||
|
@ -2598,6 +2824,11 @@ rl_menu_complete (count, ignore)
|
|||
full_completion = 1;
|
||||
return (0);
|
||||
}
|
||||
else if (_rl_menu_complete_prefix_first)
|
||||
{
|
||||
rl_ding ();
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
else if (match_list_size <= 1)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* display.c -- readline redisplay facility. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2013 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.
|
||||
|
@ -41,6 +41,10 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __MSDOS__
|
||||
# include <pc.h>
|
||||
#endif
|
||||
|
||||
/* System-specific feature definitions and include files. */
|
||||
#include "rldefs.h"
|
||||
#include "rlmbutil.h"
|
||||
|
@ -63,6 +67,7 @@ static void update_line PARAMS((char *, char *, int, int, int, int));
|
|||
static void space_to_eol PARAMS((int));
|
||||
static void delete_chars PARAMS((int));
|
||||
static void insert_some_chars PARAMS((char *, int, int));
|
||||
static void open_some_spaces PARAMS((int));
|
||||
static void cr PARAMS((void));
|
||||
|
||||
/* State of visible and invisible lines. */
|
||||
|
@ -165,6 +170,7 @@ int _rl_last_v_pos = 0;
|
|||
|
||||
static int cpos_adjusted;
|
||||
static int cpos_buffer_position;
|
||||
static int displaying_prompt_first_line;
|
||||
static int prompt_multibyte_chars;
|
||||
|
||||
/* Number of lines currently on screen minus 1. */
|
||||
|
@ -176,7 +182,8 @@ int _rl_vis_botlin = 0;
|
|||
static int last_lmargin;
|
||||
|
||||
/* A buffer for `modeline' messages. */
|
||||
static char msg_buf[128];
|
||||
static char *msg_buf = 0;
|
||||
static int msg_bufsiz = 0;
|
||||
|
||||
/* Non-zero forces the redisplay even if we thought it was unnecessary. */
|
||||
static int forced_display;
|
||||
|
@ -232,6 +239,18 @@ static int saved_local_length;
|
|||
static int saved_invis_chars_first_line;
|
||||
static int saved_physical_chars;
|
||||
|
||||
/* Return a character indicating the editing mode, for use in the prompt. */
|
||||
static int
|
||||
prompt_modechar ()
|
||||
{
|
||||
if (rl_editing_mode == emacs_mode)
|
||||
return '@';
|
||||
else if (_rl_keymap == vi_insertion_keymap)
|
||||
return '+'; /* vi insert mode */
|
||||
else
|
||||
return ':'; /* vi command mode */
|
||||
}
|
||||
|
||||
/* Expand the prompt string S and return the number of visible
|
||||
characters in *LP, if LP is not null. This is currently more-or-less
|
||||
a placeholder for expansion. LIP, if non-null is a place to store the
|
||||
|
@ -258,7 +277,16 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
|
|||
/* Short-circuit if we can. */
|
||||
if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
|
||||
{
|
||||
r = savestring (pmt);
|
||||
if (pmt == rl_prompt && _rl_show_mode_in_prompt)
|
||||
{
|
||||
l = strlen (pmt);
|
||||
r = (char *)xmalloc (l + 2);
|
||||
r[0] = prompt_modechar ();
|
||||
strcpy (r + 1, pmt);
|
||||
}
|
||||
else
|
||||
r = savestring (pmt);
|
||||
|
||||
if (lp)
|
||||
*lp = strlen (r);
|
||||
if (lip)
|
||||
|
@ -271,13 +299,20 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
|
|||
}
|
||||
|
||||
l = strlen (pmt);
|
||||
r = ret = (char *)xmalloc (l + 1);
|
||||
r = ret = (char *)xmalloc (l + 2);
|
||||
|
||||
rl = physchars = 0; /* move up here so mode show can set them */
|
||||
if (pmt == rl_prompt && _rl_show_mode_in_prompt)
|
||||
{
|
||||
*r++ = prompt_modechar ();
|
||||
rl = physchars = 1;
|
||||
}
|
||||
|
||||
invfl = 0; /* invisible chars in first line of prompt */
|
||||
invflset = 0; /* we only want to set invfl once */
|
||||
|
||||
igstart = 0;
|
||||
for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++)
|
||||
for (ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
|
||||
{
|
||||
/* This code strips the invisible character string markers
|
||||
RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
|
||||
|
@ -366,6 +401,12 @@ _rl_strip_prompt (pmt)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
_rl_reset_prompt ()
|
||||
{
|
||||
rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand the prompt string into the various display components, if
|
||||
* necessary.
|
||||
|
@ -707,10 +748,9 @@ rl_redisplay ()
|
|||
/* Now account for invisible characters in the current line. */
|
||||
/* XXX - this assumes that the invisible characters may be split, but only
|
||||
between the first and the last lines. */
|
||||
temp += ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line
|
||||
: ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line))
|
||||
: ((newlines == 0) ? wrap_offset : 0));
|
||||
|
||||
temp += (newlines == 0) ? prompt_invis_chars_first_line
|
||||
: ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line);
|
||||
|
||||
inv_lbreaks[++newlines] = temp;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
|
||||
|
@ -761,7 +801,7 @@ rl_redisplay ()
|
|||
break; /* Found '\0' */
|
||||
else
|
||||
{
|
||||
temp = wcwidth (wc);
|
||||
temp = WCWIDTH (wc);
|
||||
wc_width = (temp >= 0) ? temp : 1;
|
||||
}
|
||||
}
|
||||
|
@ -925,7 +965,7 @@ rl_redisplay ()
|
|||
/* If we can move the cursor up and down, then use multiple lines,
|
||||
otherwise, let long lines display in a single terminal line, and
|
||||
horizontally scroll it. */
|
||||
|
||||
displaying_prompt_first_line = 1;
|
||||
if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
|
||||
{
|
||||
int nleft, pos, changed_screen_line, tx;
|
||||
|
@ -1179,6 +1219,8 @@ rl_redisplay ()
|
|||
else
|
||||
lmargin = last_lmargin;
|
||||
|
||||
displaying_prompt_first_line = lmargin < nleft;
|
||||
|
||||
/* If the first character on the screen isn't the first character
|
||||
in the display line, indicate this with a special character. */
|
||||
if (lmargin > 0)
|
||||
|
@ -1204,7 +1246,8 @@ rl_redisplay ()
|
|||
_rl_screenwidth + (lmargin ? 0 : wrap_offset),
|
||||
0);
|
||||
|
||||
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
|
||||
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
|
||||
displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
|
||||
_rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
|
||||
|
||||
/* If the visible new line is shorter than the old, but the number
|
||||
|
@ -1212,7 +1255,7 @@ rl_redisplay ()
|
|||
the new line, we need to clear to eol. */
|
||||
t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
|
||||
if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
|
||||
(_rl_last_c_pos == out) &&
|
||||
(_rl_last_c_pos == out) && displaying_prompt_first_line &&
|
||||
t < visible_first_line_len)
|
||||
{
|
||||
nleft = _rl_screenwidth - t;
|
||||
|
@ -1274,6 +1317,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
|
||||
int current_invis_chars;
|
||||
int col_lendiff, col_temp;
|
||||
int bytes_to_insert;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mbstate_t ps_new, ps_old;
|
||||
int new_offset, old_offset;
|
||||
|
@ -1300,7 +1344,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
size_t ret;
|
||||
|
||||
/* This fixes only double-column characters, but if the wrapped
|
||||
character comsumes more than three columns, spaces will be
|
||||
character consumes more than three columns, spaces will be
|
||||
inserted in the string buffer. */
|
||||
if (current_line < line_state_visible->wbsize && line_state_visible->wrapped_line[current_line] > 0)
|
||||
_rl_clear_to_eol (line_state_visible->wrapped_line[current_line]);
|
||||
|
@ -1315,7 +1359,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
else if (MB_NULLWCH (ret))
|
||||
tempwidth = 0;
|
||||
else
|
||||
tempwidth = wcwidth (wc);
|
||||
tempwidth = WCWIDTH (wc);
|
||||
|
||||
if (tempwidth > 0)
|
||||
{
|
||||
|
@ -1335,7 +1379,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
memcpy (old, new, bytes);
|
||||
/* Fix up indices if we copy data from one line to another */
|
||||
omax += bytes - ret;
|
||||
for (i = current_line+1; i < inv_botlin+1; i++)
|
||||
for (i = current_line+1; i <= inv_botlin+1; i++)
|
||||
vis_lbreaks[i] += bytes - ret;
|
||||
}
|
||||
}
|
||||
|
@ -1372,6 +1416,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
temp = (omax < nmax) ? omax : nmax;
|
||||
if (memcmp (old, new, temp) == 0) /* adding at the end */
|
||||
{
|
||||
new_offset = old_offset = temp;
|
||||
ofd = old + temp;
|
||||
nfd = new + temp;
|
||||
}
|
||||
|
@ -1382,6 +1427,8 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
|
||||
if (omax == nmax && STREQN (new, old, omax))
|
||||
{
|
||||
old_offset = omax;
|
||||
new_offset = nmax;
|
||||
ofd = old + omax;
|
||||
nfd = new + nmax;
|
||||
}
|
||||
|
@ -1394,6 +1441,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
{
|
||||
old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
|
||||
new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
|
||||
|
||||
ofd = old + old_offset;
|
||||
nfd = new + new_offset;
|
||||
}
|
||||
|
@ -1417,6 +1465,27 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
if (ofd == oe && nfd == ne)
|
||||
return;
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
|
||||
{
|
||||
wchar_t wc;
|
||||
mbstate_t ps = { 0 };
|
||||
int t;
|
||||
|
||||
/* If the first character in the difference is a zero-width character,
|
||||
assume it's a combining character and back one up so the two base
|
||||
characters no longer compare equivalently. */
|
||||
t = mbrtowc (&wc, ofd, MB_CUR_MAX, &ps);
|
||||
if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
|
||||
{
|
||||
old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
|
||||
new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
|
||||
ofd = old + old_offset; /* equal by definition */
|
||||
nfd = new + new_offset;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wsatend = 1; /* flag for trailing whitespace */
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
|
@ -1424,6 +1493,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
{
|
||||
ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
|
||||
nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
|
||||
|
||||
while ((ols > ofd) && (nls > nfd))
|
||||
{
|
||||
memset (&ps_old, 0, sizeof (mbstate_t));
|
||||
|
@ -1540,10 +1610,10 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
o_cpos = _rl_last_c_pos;
|
||||
|
||||
/* When this function returns, _rl_last_c_pos is correct, and an absolute
|
||||
cursor postion in multibyte mode, but a buffer index when not in a
|
||||
cursor position in multibyte mode, but a buffer index when not in a
|
||||
multibyte locale. */
|
||||
_rl_move_cursor_relative (od, old);
|
||||
#if 1
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* We need to indicate that the cursor position is correct in the presence of
|
||||
invisible characters in the prompt string. Let's see if setting this when
|
||||
|
@ -1552,12 +1622,11 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
(_rl_last_c_pos > 0 || o_cpos > 0) &&
|
||||
_rl_last_c_pos == prompt_physical_chars)
|
||||
cpos_adjusted = 1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* if (len (new) > len (old))
|
||||
lendiff == difference in buffer
|
||||
col_lendiff == difference on screen
|
||||
lendiff == difference in buffer (bytes)
|
||||
col_lendiff == difference on screen (columns)
|
||||
When not using multibyte characters, these are equal */
|
||||
lendiff = (nls - nfd) - (ols - ofd);
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
|
@ -1583,6 +1652,10 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
}
|
||||
}
|
||||
|
||||
/* We use temp as a count of the number of bytes from the first difference
|
||||
to the end of the new line. col_temp is the corresponding number of
|
||||
screen columns. A `dumb' update moves to the spot of first difference
|
||||
and writes TEMP bytes. */
|
||||
/* Insert (diff (len (old), len (new)) ch. */
|
||||
temp = ne - nfd;
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
|
@ -1590,6 +1663,10 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
else
|
||||
col_temp = temp;
|
||||
|
||||
/* how many bytes from the new line buffer to write to the display */
|
||||
bytes_to_insert = nls - nfd;
|
||||
|
||||
/* col_lendiff > 0 if we are adding characters to the line */
|
||||
if (col_lendiff > 0) /* XXX - was lendiff */
|
||||
{
|
||||
/* Non-zero if we're increasing the number of lines. */
|
||||
|
@ -1603,11 +1680,11 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
if (lendiff < 0)
|
||||
{
|
||||
_rl_output_some_chars (nfd, temp);
|
||||
_rl_last_c_pos += _rl_col_width (nfd, 0, temp, 1);
|
||||
_rl_last_c_pos += col_temp; /* XXX - was _rl_col_width (nfd, 0, temp, 1); */
|
||||
/* If nfd begins before any invisible characters in the prompt,
|
||||
adjust _rl_last_c_pos to account for wrap_offset and set
|
||||
cpos_adjusted to let the caller know. */
|
||||
if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
|
||||
if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
|
||||
{
|
||||
_rl_last_c_pos -= wrap_offset;
|
||||
cpos_adjusted = 1;
|
||||
|
@ -1638,57 +1715,42 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
(col_lendiff < prompt_visible_length)) == 0) &&
|
||||
(visible_wrap_offset >= current_invis_chars))
|
||||
{
|
||||
insert_some_chars (nfd, lendiff, col_lendiff);
|
||||
_rl_last_c_pos += col_lendiff;
|
||||
open_some_spaces (col_lendiff);
|
||||
_rl_output_some_chars (nfd, bytes_to_insert);
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
_rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
|
||||
else
|
||||
_rl_last_c_pos += bytes_to_insert;
|
||||
}
|
||||
#if 0 /* XXX - for now */
|
||||
else if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && _rl_last_c_pos == 0 && wrap_offset && (nfd-new) <= prompt_last_invisible && col_lendiff < prompt_visible_length && visible_wrap_offset >= current_invis_chars)
|
||||
{
|
||||
_rl_output_some_chars (nfd, lendiff);
|
||||
_rl_last_c_pos += col_lendiff;
|
||||
}
|
||||
#endif
|
||||
else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
|
||||
{
|
||||
/* At the end of a line the characters do not have to
|
||||
be "inserted". They can just be placed on the screen. */
|
||||
/* However, this screws up the rest of this block, which
|
||||
assumes you've done the insert because you can. */
|
||||
_rl_output_some_chars (nfd, lendiff);
|
||||
_rl_last_c_pos += col_lendiff;
|
||||
_rl_output_some_chars (nfd, temp);
|
||||
_rl_last_c_pos += col_temp;
|
||||
return;
|
||||
}
|
||||
else
|
||||
else /* just write from first difference to end of new line */
|
||||
{
|
||||
_rl_output_some_chars (nfd, temp);
|
||||
_rl_last_c_pos += col_temp;
|
||||
/* If nfd begins before the last invisible character in the
|
||||
prompt, adjust _rl_last_c_pos to account for wrap_offset
|
||||
and set cpos_adjusted to let the caller know. */
|
||||
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
|
||||
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
|
||||
{
|
||||
_rl_last_c_pos -= wrap_offset;
|
||||
cpos_adjusted = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* Copy (new) chars to screen from first diff to last match. */
|
||||
temp = nls - nfd;
|
||||
if ((temp - lendiff) > 0)
|
||||
|
||||
if (bytes_to_insert > lendiff)
|
||||
{
|
||||
_rl_output_some_chars (nfd + lendiff, temp - lendiff);
|
||||
/* XXX -- this bears closer inspection. Fixes a redisplay bug
|
||||
reported against bash-3.0-alpha by Andreas Schwab involving
|
||||
multibyte characters and prompt strings with invisible
|
||||
characters, but was previously disabled. */
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
twidth = _rl_col_width (nfd+lendiff, 0, temp-col_lendiff, 1);
|
||||
else
|
||||
twidth = temp - lendiff;
|
||||
_rl_last_c_pos += twidth;
|
||||
/* If nfd begins before the last invisible character in the
|
||||
prompt, adjust _rl_last_c_pos to account for wrap_offset
|
||||
and set cpos_adjusted to let the caller know. */
|
||||
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
|
||||
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
|
||||
{
|
||||
_rl_last_c_pos -= wrap_offset;
|
||||
cpos_adjusted = 1;
|
||||
|
@ -1706,6 +1768,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
a physical character position. */
|
||||
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
|
||||
current_line == prompt_last_screen_line && wrap_offset &&
|
||||
displaying_prompt_first_line &&
|
||||
wrap_offset != prompt_invis_chars_first_line &&
|
||||
((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth))))
|
||||
{
|
||||
|
@ -1723,32 +1786,47 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
prompt string, don't bother. It screws up the assumptions
|
||||
about what's on the screen. */
|
||||
if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
|
||||
displaying_prompt_first_line &&
|
||||
-lendiff == visible_wrap_offset)
|
||||
col_lendiff = 0;
|
||||
|
||||
/* If we have moved lmargin and we're shrinking the line, we've
|
||||
already moved the cursor to the first character of the new line,
|
||||
so deleting -col_lendiff characters will mess up the cursor
|
||||
position calculation */
|
||||
if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
|
||||
col_lendiff && _rl_last_c_pos < -col_lendiff)
|
||||
col_lendiff = 0;
|
||||
|
||||
if (col_lendiff)
|
||||
delete_chars (-col_lendiff); /* delete (diff) characters */
|
||||
|
||||
/* Copy (new) chars to screen from first diff to last match */
|
||||
temp = nls - nfd;
|
||||
if (temp > 0)
|
||||
/* Copy (new) chars to screen from first diff to last match,
|
||||
overwriting what is there. */
|
||||
if (bytes_to_insert > 0)
|
||||
{
|
||||
/* If nfd begins at the prompt, or before the invisible
|
||||
characters in the prompt, we need to adjust _rl_last_c_pos
|
||||
in a multibyte locale to account for the wrap offset and
|
||||
set cpos_adjusted accordingly. */
|
||||
_rl_output_some_chars (nfd, temp);
|
||||
_rl_output_some_chars (nfd, bytes_to_insert);
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
_rl_last_c_pos += _rl_col_width (nfd, 0, temp, 1);
|
||||
if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
|
||||
_rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
|
||||
if (current_line == 0 && wrap_offset &&
|
||||
displaying_prompt_first_line &&
|
||||
_rl_last_c_pos > wrap_offset &&
|
||||
((nfd - new) <= prompt_last_invisible))
|
||||
{
|
||||
_rl_last_c_pos -= wrap_offset;
|
||||
cpos_adjusted = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
_rl_last_c_pos += temp;
|
||||
_rl_last_c_pos += bytes_to_insert;
|
||||
|
||||
if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
|
||||
goto clear_rest_of_line;
|
||||
}
|
||||
}
|
||||
/* Otherwise, print over the existing material. */
|
||||
|
@ -1764,29 +1842,29 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
_rl_last_c_pos += col_temp; /* XXX */
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
|
||||
if (current_line == 0 && wrap_offset &&
|
||||
displaying_prompt_first_line &&
|
||||
_rl_last_c_pos > wrap_offset &&
|
||||
((nfd - new) <= prompt_last_invisible))
|
||||
{
|
||||
_rl_last_c_pos -= wrap_offset;
|
||||
cpos_adjusted = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
clear_rest_of_line:
|
||||
lendiff = (oe - old) - (ne - new);
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
|
||||
else
|
||||
col_lendiff = lendiff;
|
||||
|
||||
#if 0
|
||||
if (col_lendiff)
|
||||
#else
|
||||
/* If we've already printed over the entire width of the screen,
|
||||
including the old material, then col_lendiff doesn't matter and
|
||||
space_to_eol will insert too many spaces. XXX - maybe we should
|
||||
adjust col_lendiff based on the difference between _rl_last_c_pos
|
||||
and _rl_screenwidth */
|
||||
if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
|
||||
#endif
|
||||
{
|
||||
if (_rl_term_autowrap && current_line < inv_botlin)
|
||||
space_to_eol (col_lendiff);
|
||||
|
@ -1938,6 +2016,9 @@ _rl_move_cursor_relative (new, data)
|
|||
else
|
||||
dpos = _rl_col_width (data, 0, new, 1);
|
||||
|
||||
if (displaying_prompt_first_line == 0)
|
||||
adjust = 0;
|
||||
|
||||
/* Use NEW when comparing against the last invisible character in the
|
||||
prompt string, since they're both buffer indices and DPOS is a
|
||||
desired display position. */
|
||||
|
@ -2056,9 +2137,18 @@ _rl_move_vert (to)
|
|||
}
|
||||
else
|
||||
{ /* delta < 0 */
|
||||
#ifdef __DJGPP__
|
||||
int row, col;
|
||||
|
||||
fflush (rl_outstream);
|
||||
ScreenGetCursor (&row, &col);
|
||||
ScreenSetCursor (row + delta, col);
|
||||
i = -delta;
|
||||
#else
|
||||
if (_rl_term_up && *_rl_term_up)
|
||||
for (i = 0; i < -delta; i++)
|
||||
tputs (_rl_term_up, 1, _rl_output_character_function);
|
||||
#endif /* !__DJGPP__ */
|
||||
}
|
||||
|
||||
_rl_last_v_pos = to; /* Now TO is here */
|
||||
|
@ -2136,6 +2226,9 @@ rl_message (va_alist)
|
|||
#if defined (PREFER_VARARGS)
|
||||
char *format;
|
||||
#endif
|
||||
#if defined (HAVE_VSNPRINTF)
|
||||
int bneed;
|
||||
#endif
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
|
@ -2144,11 +2237,28 @@ rl_message (va_alist)
|
|||
format = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
if (msg_buf == 0)
|
||||
msg_buf = xmalloc (msg_bufsiz = 128);
|
||||
|
||||
#if defined (HAVE_VSNPRINTF)
|
||||
vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
|
||||
bneed = vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
|
||||
if (bneed >= msg_bufsiz - 1)
|
||||
{
|
||||
msg_bufsiz = bneed + 1;
|
||||
msg_buf = xrealloc (msg_buf, msg_bufsiz);
|
||||
va_end (args);
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
#else
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
#endif
|
||||
vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
|
||||
}
|
||||
#else
|
||||
vsprintf (msg_buf, format, args);
|
||||
msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
|
||||
msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
|
||||
#endif
|
||||
va_end (args);
|
||||
|
||||
|
@ -2157,6 +2267,12 @@ rl_message (va_alist)
|
|||
rl_save_prompt ();
|
||||
msg_saved_prompt = 1;
|
||||
}
|
||||
else if (local_prompt != saved_local_prompt)
|
||||
{
|
||||
FREE (local_prompt);
|
||||
FREE (local_prompt_prefix);
|
||||
local_prompt = (char *)NULL;
|
||||
}
|
||||
rl_display_prompt = msg_buf;
|
||||
local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
|
||||
&prompt_last_invisible,
|
||||
|
@ -2173,8 +2289,11 @@ int
|
|||
rl_message (format, arg1, arg2)
|
||||
char *format;
|
||||
{
|
||||
if (msg_buf == 0)
|
||||
msg_buf = xmalloc (msg_bufsiz = 128);
|
||||
|
||||
sprintf (msg_buf, format, arg1, arg2);
|
||||
msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
|
||||
msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
|
||||
|
||||
rl_display_prompt = msg_buf;
|
||||
if (saved_local_prompt == 0)
|
||||
|
@ -2182,6 +2301,12 @@ rl_message (format, arg1, arg2)
|
|||
rl_save_prompt ();
|
||||
msg_saved_prompt = 1;
|
||||
}
|
||||
else if (local_prompt != saved_local_prompt)
|
||||
{
|
||||
FREE (local_prompt);
|
||||
FREE (local_prompt_prefix);
|
||||
local_prompt = (char *)NULL;
|
||||
}
|
||||
local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
|
||||
&prompt_last_invisible,
|
||||
&prompt_invis_chars_first_line,
|
||||
|
@ -2318,10 +2443,13 @@ void
|
|||
_rl_clear_to_eol (count)
|
||||
int count;
|
||||
{
|
||||
#ifndef __MSDOS__
|
||||
if (_rl_term_clreol)
|
||||
tputs (_rl_term_clreol, 1, _rl_output_character_function);
|
||||
else if (count)
|
||||
space_to_eol (count);
|
||||
else
|
||||
#endif
|
||||
if (count)
|
||||
space_to_eol (count);
|
||||
}
|
||||
|
||||
/* Clear to the end of the line using spaces. COUNT is the minimum
|
||||
|
@ -2341,10 +2469,15 @@ space_to_eol (count)
|
|||
void
|
||||
_rl_clear_screen ()
|
||||
{
|
||||
#ifndef __DJGPP__
|
||||
if (_rl_term_clrpag)
|
||||
tputs (_rl_term_clrpag, 1, _rl_output_character_function);
|
||||
else
|
||||
rl_crlf ();
|
||||
#else
|
||||
ScreenClear ();
|
||||
ScreenSetCursor (0, 0);
|
||||
#endif /* __DJGPP__ */
|
||||
}
|
||||
|
||||
/* Insert COUNT characters from STRING to the output stream at column COL. */
|
||||
|
@ -2353,48 +2486,47 @@ insert_some_chars (string, count, col)
|
|||
char *string;
|
||||
int count, col;
|
||||
{
|
||||
#if defined (__MSDOS__) || defined (__MINGW32__)
|
||||
open_some_spaces (col);
|
||||
_rl_output_some_chars (string, count);
|
||||
#else
|
||||
/* DEBUGGING */
|
||||
if (MB_CUR_MAX == 1 || rl_byte_oriented)
|
||||
if (count != col)
|
||||
_rl_ttymsg ("debug: insert_some_chars: count (%d) != col (%d)", count, col);
|
||||
}
|
||||
|
||||
/* Insert COL spaces, keeping the cursor at the same position. We follow the
|
||||
ncurses documentation and use either im/ei with explicit spaces, or IC/ic
|
||||
by itself. We assume there will either be ei or we don't need to use it. */
|
||||
static void
|
||||
open_some_spaces (col)
|
||||
int col;
|
||||
{
|
||||
#if !defined (__MSDOS__) && !defined (__MINGW32__)
|
||||
char *buffer;
|
||||
register int i;
|
||||
|
||||
/* If IC is defined, then we do not have to "enter" insert mode. */
|
||||
if (_rl_term_IC)
|
||||
{
|
||||
char *buffer;
|
||||
|
||||
buffer = tgoto (_rl_term_IC, 0, col);
|
||||
tputs (buffer, 1, _rl_output_character_function);
|
||||
_rl_output_some_chars (string, count);
|
||||
}
|
||||
else
|
||||
else if (_rl_term_im && *_rl_term_im)
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* If we have to turn on insert-mode, then do so. */
|
||||
if (_rl_term_im && *_rl_term_im)
|
||||
tputs (_rl_term_im, 1, _rl_output_character_function);
|
||||
|
||||
/* If there is a special command for inserting characters, then
|
||||
use that first to open up the space. */
|
||||
if (_rl_term_ic && *_rl_term_ic)
|
||||
{
|
||||
for (i = col; i--; )
|
||||
tputs (_rl_term_ic, 1, _rl_output_character_function);
|
||||
}
|
||||
|
||||
/* Print the text. */
|
||||
_rl_output_some_chars (string, count);
|
||||
|
||||
/* If there is a string to turn off insert mode, we had best use
|
||||
it now. */
|
||||
tputs (_rl_term_im, 1, _rl_output_character_function);
|
||||
/* just output the desired number of spaces */
|
||||
for (i = col; i--; )
|
||||
_rl_output_character_function (' ');
|
||||
/* If there is a string to turn off insert mode, use it now. */
|
||||
if (_rl_term_ei && *_rl_term_ei)
|
||||
tputs (_rl_term_ei, 1, _rl_output_character_function);
|
||||
/* and move back the right number of spaces */
|
||||
_rl_backspace (col);
|
||||
}
|
||||
#endif /* __MSDOS__ || __MINGW32__ */
|
||||
else if (_rl_term_ic && *_rl_term_ic)
|
||||
{
|
||||
/* If there is a special command for inserting characters, then
|
||||
use that first to open up the space. */
|
||||
for (i = col; i--; )
|
||||
tputs (_rl_term_ic, 1, _rl_output_character_function);
|
||||
}
|
||||
#endif /* !__MSDOS__ && !__MINGW32__ */
|
||||
}
|
||||
|
||||
/* Delete COUNT characters from the display line. */
|
||||
|
@ -2599,10 +2731,8 @@ _rl_col_width (str, start, end, flags)
|
|||
if (end <= start)
|
||||
return 0;
|
||||
if (MB_CUR_MAX == 1 || rl_byte_oriented)
|
||||
{
|
||||
_rl_ttymsg ("_rl_col_width: called with MB_CUR_MAX == 1");
|
||||
/* this can happen in some cases where it's inconvenient to check */
|
||||
return (end - start);
|
||||
}
|
||||
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
|
||||
|
@ -2676,7 +2806,7 @@ _rl_ttymsg ("_rl_col_width: called with MB_CUR_MAX == 1");
|
|||
{
|
||||
point += tmp;
|
||||
max -= tmp;
|
||||
tmp = wcwidth(wc);
|
||||
tmp = WCWIDTH(wc);
|
||||
width += (tmp >= 0) ? tmp : 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,33 +2,25 @@
|
|||
@c %**start of header (This is for running Texinfo on a region.)
|
||||
@setfilename history.info
|
||||
@settitle GNU History Library
|
||||
@c %**end of header (This is for running Texinfo on a region.)
|
||||
|
||||
@include version.texi
|
||||
|
||||
@c %**end of header (This is for running Texinfo on a region.)
|
||||
|
||||
@copying
|
||||
This document describes the GNU History library
|
||||
(version @value{VERSION}, @value{UPDATED}),
|
||||
a programming tool that provides a consistent user interface for
|
||||
recalling lines of previously typed input.
|
||||
|
||||
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
|
||||
are preserved on all copies.
|
||||
Copyright @copyright{} 1988--2014 Free Software Foundation, Inc.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with the Front-Cover texts being ``A GNU Manual'',
|
||||
and with the Back-Cover Texts as in (a) below. A copy of the license is
|
||||
included in the section entitled ``GNU Free Documentation License''.
|
||||
|
||||
(a) The FSF's Back-Cover Text is: You are free to copy and modify
|
||||
this GNU manual. Buying copies from GNU Press supports the FSF in
|
||||
developing GNU and promoting software freedom.''
|
||||
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
|
||||
A copy of the license is included in the section entitled
|
||||
``GNU Free Documentation License''.
|
||||
|
||||
@end quotation
|
||||
@end copying
|
||||
|
@ -50,12 +42,6 @@ developing GNU and promoting software freedom.''
|
|||
@vskip 0pt plus 1filll
|
||||
@insertcopying
|
||||
|
||||
@sp 1
|
||||
Published by the Free Software Foundation @*
|
||||
59 Temple Place, Suite 330, @*
|
||||
Boston, MA 02111-1307 @*
|
||||
USA @*
|
||||
|
||||
@end titlepage
|
||||
|
||||
@contents
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@ignore
|
||||
This file documents the user interface to the GNU History library.
|
||||
|
||||
Copyright (C) 1988-2011 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2014 Free Software Foundation, Inc.
|
||||
Authored by Brian Fox and Chet Ramey.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this manual
|
||||
|
@ -377,7 +377,7 @@ if the returned line should be displayed, but not executed,
|
|||
as with the @code{:p} modifier (@pxref{Modifiers}).
|
||||
@end table
|
||||
|
||||
If an error ocurred in expansion, then @var{output} contains a descriptive
|
||||
If an error occurred in expansion, then @var{output} contains a descriptive
|
||||
error message.
|
||||
@end deftypefun
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@ignore
|
||||
This file documents the user interface to the GNU History library.
|
||||
|
||||
Copyright (C) 1988--2011 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988--2014 Free Software Foundation, Inc.
|
||||
Authored by Brian Fox and Chet Ramey.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this manual
|
||||
|
@ -84,17 +84,18 @@ file named by the @env{HISTFILE} variable (default @file{~/.bash_history}).
|
|||
The file named by the value of @env{HISTFILE} is truncated, if
|
||||
necessary, to contain no more than the number of lines specified by
|
||||
the value of the @env{HISTFILESIZE} variable.
|
||||
When an interactive shell exits, the last
|
||||
When a shell with history enabled exits, the last
|
||||
@env{$HISTSIZE} lines are copied from the history list to the file
|
||||
named by @env{$HISTFILE}.
|
||||
If the @code{histappend} shell option is set (@pxref{Bash Builtins}),
|
||||
the lines are appended to the history file,
|
||||
otherwise the history file is overwritten.
|
||||
If @env{HISTFILE}
|
||||
is unset, or if the history file is unwritable, the history is
|
||||
not saved. After saving the history, the history file is truncated
|
||||
to contain no more than @env{$HISTFILESIZE}
|
||||
lines. If @env{HISTFILESIZE} is not set, no truncation is performed.
|
||||
is unset, or if the history file is unwritable, the history is not saved.
|
||||
After saving the history, the history file is truncated
|
||||
to contain no more than @env{$HISTFILESIZE} lines.
|
||||
If @env{HISTFILESIZE} is unset, or set to null, a non-numeric value, or
|
||||
a numeric value less than zero, the history file is not truncated.
|
||||
|
||||
If the @env{HISTTIMEFORMAT} is set, the time stamp information
|
||||
associated with each history entry is written to the history file,
|
||||
|
@ -141,8 +142,10 @@ history list and history file.
|
|||
@code{fc -s [@var{pat}=@var{rep}] [@var{command}]}
|
||||
@end example
|
||||
|
||||
Fix Command. In the first form, a range of commands from @var{first} to
|
||||
@var{last} is selected from the history list. Both @var{first} and
|
||||
The first form selects a range of commands from @var{first} to
|
||||
@var{last} from the history list and displays or edits and re-executes
|
||||
them.
|
||||
Both @var{first} and
|
||||
@var{last} may be specified as a string (to locate the most recent
|
||||
command beginning with that string) or as a number (an index into the
|
||||
history list, where a negative number is used as an offset from the
|
||||
|
@ -161,6 +164,7 @@ When editing is complete, the edited commands are echoed and executed.
|
|||
|
||||
In the second form, @var{command} is re-executed after each instance
|
||||
of @var{pat} in the selected command is replaced by @var{rep}.
|
||||
@var{command} is intepreted the same as @var{first} above.
|
||||
|
||||
A useful alias to use with the @code{fc} command is @code{r='fc -s'}, so
|
||||
that typing @samp{r cc} runs the last command beginning with @code{cc}
|
||||
|
@ -208,11 +212,11 @@ to the current history list. These are lines appended to the history
|
|||
file since the beginning of the current Bash session.
|
||||
|
||||
@item -r
|
||||
Read the current history file and append its contents to
|
||||
Read the history file and append its contents to
|
||||
the history list.
|
||||
|
||||
@item -w
|
||||
Write out the current history to the history file.
|
||||
Write out the current history list to the history file.
|
||||
|
||||
@item -p
|
||||
Perform history substitution on the @var{arg}s and display the result
|
||||
|
|
|
@ -2,34 +2,26 @@
|
|||
@comment %**start of header (This is for running Texinfo on a region.)
|
||||
@setfilename readline.info
|
||||
@settitle GNU Readline Library
|
||||
@include version.texi
|
||||
|
||||
@comment %**end of header (This is for running Texinfo on a region.)
|
||||
@synindex vr fn
|
||||
|
||||
@include version.texi
|
||||
|
||||
@copying
|
||||
This manual describes the GNU Readline Library
|
||||
(version @value{VERSION}, @value{UPDATED}), a library which aids in the
|
||||
consistency of user interface across discrete programs which provide
|
||||
a command line interface.
|
||||
|
||||
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
|
||||
are preserved on all copies.
|
||||
Copyright @copyright{} 1988--2014 Free Software Foundation, Inc.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with the Front-Cover texts being ``A GNU Manual'',
|
||||
and with the Back-Cover Texts as in (a) below. A copy of the license is
|
||||
included in the section entitled ``GNU Free Documentation License''.
|
||||
|
||||
(a) The FSF's Back-Cover Text is: You are free to copy and modify
|
||||
this GNU manual. Buying copies from GNU Press supports the FSF in
|
||||
developing GNU and promoting software freedom.''
|
||||
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
|
||||
A copy of the license is included in the section entitled
|
||||
``GNU Free Documentation License''.
|
||||
|
||||
@end quotation
|
||||
@end copying
|
||||
|
@ -50,12 +42,6 @@ developing GNU and promoting software freedom.''
|
|||
@vskip 0pt plus 1filll
|
||||
@insertcopying
|
||||
|
||||
@sp 1
|
||||
Published by the Free Software Foundation @*
|
||||
59 Temple Place, Suite 330, @*
|
||||
Boston, MA 02111-1307 @*
|
||||
USA @*
|
||||
|
||||
@end titlepage
|
||||
|
||||
@contents
|
||||
|
@ -67,6 +53,7 @@ USA @*
|
|||
This document describes the GNU Readline Library, a utility which aids
|
||||
in the consistency of user interface across discrete programs which
|
||||
provide a command line interface.
|
||||
The Readline home page is @url{http://www.gnu.org/software/readline/}.
|
||||
|
||||
@menu
|
||||
* Command Line Editing:: GNU Readline User's Manual.
|
||||
|
|
|
@ -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--2011 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988--2014 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
|
@ -195,7 +195,7 @@ For Readline 4.2, for example, the value of
|
|||
@node Readline Typedefs
|
||||
@subsection Readline Typedefs
|
||||
|
||||
For readabilty, we declare a number of new object types, all pointers
|
||||
For readability, we declare a number of new object types, all pointers
|
||||
to functions.
|
||||
|
||||
The reason for declaring these new types is to make it easier to write
|
||||
|
@ -440,6 +440,35 @@ If non-zero, Readline will call indirectly through this pointer
|
|||
to get a character from the input stream. By default, it is set to
|
||||
@code{rl_getc}, the default Readline character input function
|
||||
(@pxref{Character Input}).
|
||||
In general, an application that sets @var{rl_getc_function} should consider
|
||||
setting @var{rl_input_available_hook} as well.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {rl_hook_func_t *} rl_signal_event_hook
|
||||
If non-zero, this is the address of a function to call if a read system
|
||||
call is interrupted when Readline is reading terminal input.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {rl_hook_func_t *} rl_input_available_hook
|
||||
If non-zero, Readline will use this function's return value when it needs
|
||||
to determine whether or not there is available input on the current input
|
||||
source.
|
||||
The default hook checks @code{rl_instream}; if an application is using a
|
||||
different input source, it should set the hook appropriately.
|
||||
Readline queries for available input when implementing intra-key-sequence
|
||||
timeouts during input and incremental searches.
|
||||
This may use an application-specific timeout before returning a value;
|
||||
Readline uses the value passed to @code{rl_set_keyboard_input_timeout()}
|
||||
or the value of the user-settable @var{keyseq-timeout} variable.
|
||||
This is designed for use by applications using Readline's callback interface
|
||||
(@pxref{Alternate Interface}), which may not use the traditional
|
||||
@code{read(2)} and file descriptor interface, or other applications using
|
||||
a different input mechanism.
|
||||
If an application uses an input mechanism or hook that can potentially exceed
|
||||
the value of @var{keyseq-timeout}, it should increase the timeout or set
|
||||
this hook appropriately even when not using the callback interface.
|
||||
In general, an application that sets @var{rl_getc_function} should consider
|
||||
setting @var{rl_input_available_hook} as well.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {rl_voidfunc_t *} rl_redisplay_function
|
||||
|
@ -479,6 +508,19 @@ last key binding occurred.
|
|||
This variable is set to the text of any currently-executing macro.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar int rl_executing_key
|
||||
The key that caused the dispatch to the currently-executing Readline function.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {char *} rl_executing_keyseq
|
||||
The full key sequence that caused the dispatch to the currently-executing
|
||||
Readline function.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar int rl_key_sequence_length
|
||||
The number of characters in @var{rl_executing_keyseq}.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {int} rl_readline_state
|
||||
A variable with bit values that encapsulate the current Readline state.
|
||||
A bit is set with the @code{RL_SETSTATE} macro, and unset with the
|
||||
|
@ -487,7 +529,7 @@ whether a particular state bit is set. Current state bits include:
|
|||
|
||||
@table @code
|
||||
@item RL_STATE_NONE
|
||||
Readline has not yet been called, nor has it begun to intialize.
|
||||
Readline has not yet been called, nor has it begun to initialize.
|
||||
@item RL_STATE_INITIALIZING
|
||||
Readline is initializing its internal data structures.
|
||||
@item RL_STATE_INITIALIZED
|
||||
|
@ -580,6 +622,7 @@ means that vi mode is active.
|
|||
* Miscellaneous Functions:: Functions that don't fall into any category.
|
||||
* Alternate Interface:: Using Readline in a `callback' fashion.
|
||||
* A Readline Example:: An example Readline function.
|
||||
* Alternate Interface Example:: An example program using the alternate interface.
|
||||
@end menu
|
||||
|
||||
@node Function Naming
|
||||
|
@ -908,7 +951,7 @@ Readline thinks the screen display is correct.
|
|||
|
||||
@deftypefun int rl_on_new_line (void)
|
||||
Tell the update functions that we have moved onto a new (empty) line,
|
||||
usually after ouputting a newline.
|
||||
usually after outputting a newline.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int rl_on_new_line_with_prompt (void)
|
||||
|
@ -1241,21 +1284,29 @@ use all of a terminal's capabilities, and this function will return
|
|||
values for only those capabilities Readline uses.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {void} rl_clear_history (void)
|
||||
Clear the history list by deleting all of the entries, in the same manner
|
||||
as the History library's @code{clear_history()} function.
|
||||
This differs from @code{clear_history} because it frees private data
|
||||
Readline saves in the history list.
|
||||
@end deftypefun
|
||||
|
||||
@node Alternate Interface
|
||||
@subsection Alternate Interface
|
||||
|
||||
An alternate interface is available to plain @code{readline()}. Some
|
||||
applications need to interleave keyboard I/O with file, device, or
|
||||
window system I/O, typically by using a main loop to @code{select()}
|
||||
on various file descriptors. To accomodate this need, readline can
|
||||
on various file descriptors. To accommodate this need, readline can
|
||||
also be invoked as a `callback' function from an event loop. There
|
||||
are functions available to make this easy.
|
||||
|
||||
@deftypefun void rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *lhandler)
|
||||
Set up the terminal for readline I/O and display the initial
|
||||
expanded value of @var{prompt}. Save the value of @var{lhandler} to
|
||||
use as a function to call when a complete line of input has been entered.
|
||||
The function takes the text of the line as an argument.
|
||||
use as a handler function to call when a complete line of input has been
|
||||
entered.
|
||||
The handler function receives the text of the line as an argument.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void rl_callback_read_char (void)
|
||||
|
@ -1263,14 +1314,15 @@ Whenever an application determines that keyboard input is available, it
|
|||
should call @code{rl_callback_read_char()}, which will read the next
|
||||
character from the current input source.
|
||||
If that character completes the line, @code{rl_callback_read_char} will
|
||||
invoke the @var{lhandler} function saved by @code{rl_callback_handler_install}
|
||||
to process the line.
|
||||
invoke the @var{lhandler} function installed by
|
||||
@code{rl_callback_handler_install} to process the line.
|
||||
Before calling the @var{lhandler} function, the terminal settings are
|
||||
reset to the values they had before calling
|
||||
@code{rl_callback_handler_install}.
|
||||
If the @var{lhandler} function returns,
|
||||
and the line handler remains installed,
|
||||
the terminal settings are modified for Readline's use again.
|
||||
@code{EOF} is indicated by calling @var{lhandler} with a
|
||||
@code{EOF} is indicated by calling @var{lhandler} with a
|
||||
@code{NULL} line.
|
||||
@end deftypefun
|
||||
|
||||
|
@ -1350,6 +1402,98 @@ invert_case_line (count, key)
|
|||
@}
|
||||
@end example
|
||||
|
||||
@node Alternate Interface Example
|
||||
@subsection Alternate Interface Example
|
||||
|
||||
Here is a complete program that illustrates Readline's alternate interface.
|
||||
It reads lines from the terminal and displays them, providing the
|
||||
standard history and TAB completion functions.
|
||||
It understands the EOF character or "exit" to exit the program.
|
||||
|
||||
@example
|
||||
/* Standard include files. stdio.h is required. */
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Used for select(2) */
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Standard readline include files. */
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
static void cb_linehandler (char *);
|
||||
|
||||
int running;
|
||||
const char *prompt = "rltest$ ";
|
||||
|
||||
/* Callback function called for each line when accept-line executed, EOF
|
||||
seen, or EOF character read. This sets a flag and returns; it could
|
||||
also call exit(3). */
|
||||
static void
|
||||
cb_linehandler (char *line)
|
||||
@{
|
||||
/* Can use ^D (stty eof) or `exit' to exit. */
|
||||
if (line == NULL || strcmp (line, "exit") == 0)
|
||||
@{
|
||||
if (line == 0)
|
||||
printf ("\n");
|
||||
printf ("exit\n");
|
||||
/* This function needs to be called to reset the terminal settings,
|
||||
and calling it from the line handler keeps one extra prompt from
|
||||
being displayed. */
|
||||
rl_callback_handler_remove ();
|
||||
|
||||
running = 0;
|
||||
@}
|
||||
else
|
||||
@{
|
||||
if (*line)
|
||||
add_history (line);
|
||||
printf ("input line: %s\n", line);
|
||||
free (line);
|
||||
@}
|
||||
@}
|
||||
|
||||
int
|
||||
main (int c, char **v)
|
||||
@{
|
||||
fd_set fds;
|
||||
int r;
|
||||
|
||||
/* Install the line handler. */
|
||||
rl_callback_handler_install (prompt, cb_linehandler);
|
||||
|
||||
/* Enter a simple event loop. This waits until something is available
|
||||
to read on readline's input stream (defaults to standard input) and
|
||||
calls the builtin character read callback to read it. It does not
|
||||
have to modify the user's terminal settings. */
|
||||
running = 1;
|
||||
while (running)
|
||||
@{
|
||||
FD_ZERO (&fds);
|
||||
FD_SET (fileno (rl_instream), &fds);
|
||||
|
||||
r = select (FD_SETSIZE, &fds, NULL, NULL, NULL);
|
||||
if (r < 0)
|
||||
@{
|
||||
perror ("rltest: select");
|
||||
rl_callback_handler_remove ();
|
||||
break;
|
||||
@}
|
||||
|
||||
if (FD_ISSET (fileno (rl_instream), &fds))
|
||||
rl_callback_read_char ();
|
||||
@}
|
||||
|
||||
printf ("rltest: Event loop has exited\n");
|
||||
return 0;
|
||||
@}
|
||||
@end example
|
||||
|
||||
@node Readline Signal Handling
|
||||
@section Readline Signal Handling
|
||||
|
||||
|
@ -1365,6 +1509,7 @@ functions to do so manually.
|
|||
|
||||
Readline contains an internal signal handler that is installed for a
|
||||
number of signals (@code{SIGINT}, @code{SIGQUIT}, @code{SIGTERM},
|
||||
@code{SIGHUP},
|
||||
@code{SIGALRM}, @code{SIGTSTP}, @code{SIGTTIN}, and @code{SIGTTOU}).
|
||||
When one of these signals is received, the signal handler
|
||||
will reset the terminal attributes to those that were in effect before
|
||||
|
@ -1397,19 +1542,28 @@ a signal handler, so Readline's internal signal state is not corrupted.
|
|||
|
||||
@deftypevar int rl_catch_signals
|
||||
If this variable is non-zero, Readline will install signal handlers for
|
||||
@code{SIGINT}, @code{SIGQUIT}, @code{SIGTERM}, @code{SIGALRM},
|
||||
@code{SIGINT}, @code{SIGQUIT}, @code{SIGTERM}, @code{SIGHUP}, @code{SIGALRM},
|
||||
@code{SIGTSTP}, @code{SIGTTIN}, and @code{SIGTTOU}.
|
||||
|
||||
The default value of @code{rl_catch_signals} is 1.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar int rl_catch_sigwinch
|
||||
If this variable is non-zero, Readline will install a signal handler for
|
||||
@code{SIGWINCH}.
|
||||
If this variable is set to a non-zero value,
|
||||
Readline will install a signal handler for @code{SIGWINCH}.
|
||||
|
||||
The default value of @code{rl_catch_sigwinch} is 1.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar int rl_change_environment
|
||||
If this variable is set to a non-zero value,
|
||||
and Readline is handling @code{SIGWINCH}, Readline will modify the
|
||||
@var{LINES} and @var{COLUMNS} environment variables upon receipt of a
|
||||
@code{SIGWINCH}
|
||||
|
||||
The default value of @code{rl_change_environment} is 1.
|
||||
@end deftypevar
|
||||
|
||||
If an application does not wish to have Readline catch any signals, or
|
||||
to handle signals other than those Readline catches (@code{SIGHUP},
|
||||
for example),
|
||||
|
@ -1477,7 +1631,7 @@ The following functions install and remove Readline's signal handlers.
|
|||
|
||||
@deftypefun int rl_set_signals (void)
|
||||
Install Readline's signal handler for @code{SIGINT}, @code{SIGQUIT},
|
||||
@code{SIGTERM}, @code{SIGALRM}, @code{SIGTSTP}, @code{SIGTTIN},
|
||||
@code{SIGTERM}, @code{SIGHUP}, @code{SIGALRM}, @code{SIGTSTP}, @code{SIGTTIN},
|
||||
@code{SIGTTOU}, and @code{SIGWINCH}, depending on the values of
|
||||
@code{rl_catch_signals} and @code{rl_catch_sigwinch}.
|
||||
@end deftypefun
|
||||
|
@ -1611,7 +1765,7 @@ This calls @code{rl_complete_internal()} with an argument of @samp{*}.
|
|||
@end deftypefun
|
||||
|
||||
@deftypefun int rl_completion_mode (rl_command_func_t *cfunc)
|
||||
Returns the apppriate value to pass to @code{rl_complete_internal()}
|
||||
Returns the appropriate value to pass to @code{rl_complete_internal()}
|
||||
depending on whether @var{cfunc} was called twice in succession and
|
||||
the values of the @code{show-all-if-ambiguous} and
|
||||
@code{show-all-if-unmodified} variables.
|
||||
|
@ -1728,29 +1882,45 @@ the directory portion of the pathname the user typed.
|
|||
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
|
||||
@deftypevar extern rl_icppfunc_t *rl_directory_rewrite_hook;
|
||||
@deftypevar {rl_icppfunc_t *} rl_directory_rewrite_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 @code{rl_directory_completion_hook},
|
||||
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.
|
||||
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()}.
|
||||
|
||||
I'm not happy with how this works yet, so it's undocumented.
|
||||
The directory rewrite hook returns an integer that should be non-zero if
|
||||
the function modfies its directory argument.
|
||||
The function should not modify the directory argument if it returns 0.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {rl_icppfunc_t *} rl_filename_stat_hook
|
||||
If non-zero, this is the address of a function for the completer to
|
||||
call before deciding which character to append to a completed name.
|
||||
This function modifies its filename name argument, and the modified value
|
||||
is passed to @code{stat()} to determine the file's type and characteristics.
|
||||
This function does not need to remove quote characters from the filename.
|
||||
|
||||
The stat hook returns an integer that should be non-zero if
|
||||
the function modfies its directory argument.
|
||||
The function should not modify the directory argument if it returns 0.
|
||||
@end deftypevar
|
||||
@end ignore
|
||||
|
||||
@deftypevar {rl_dequote_func_t *} rl_filename_rewrite_hook
|
||||
If non-zero, this is the address of a function called when reading
|
||||
directory entries from the filesystem for completion and comparing
|
||||
them to the partial word to be completed. The function should
|
||||
perform any necesary application or system-specific conversion on
|
||||
perform any necessary application or system-specific conversion on
|
||||
the filename, such as converting between character sets or converting
|
||||
from a filesystem format to a character input format.
|
||||
The function takes two arguments: @var{fname}, the filename to be converted,
|
||||
|
|
|
@ -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--2011 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988--2014 Free Software Foundation, Inc.
|
||||
|
||||
Authored by Brian Fox and Chet Ramey.
|
||||
|
||||
|
@ -72,6 +72,8 @@ Line editing can be enabled at any time using the @option{-o emacs} or
|
|||
a specific command.
|
||||
* Programmable Completion Builtins:: Builtin commands to specify how to
|
||||
complete arguments for a particular command.
|
||||
* A Programmable Completion Example:: An example shell function for
|
||||
generating possible completions.
|
||||
@end ifset
|
||||
@end menu
|
||||
|
||||
|
@ -425,6 +427,14 @@ If set to @samp{on}, Readline attempts to bind the control characters
|
|||
treated specially by the kernel's terminal driver to their Readline
|
||||
equivalents.
|
||||
|
||||
@item colored-stats
|
||||
@vindex colored-stats
|
||||
If set to @samp{on}, Readline displays possible completions using different
|
||||
colors to indicate their file type.
|
||||
The color definitions are taken from the value of the @env{LS_COLORS}
|
||||
environment variable.
|
||||
The default is @samp{off}.
|
||||
|
||||
@item comment-begin
|
||||
@vindex comment-begin
|
||||
The string to insert at the beginning of the line when the
|
||||
|
@ -521,8 +531,12 @@ or @code{next-history}. The default is @samp{off}.
|
|||
|
||||
@item history-size
|
||||
@vindex history-size
|
||||
Set the maximum number of history entries saved in the history list. If
|
||||
set to zero, the number of entries in the history list is not limited.
|
||||
Set the maximum number of history entries saved in the history list.
|
||||
If set to zero, any existing history entries are deleted and no new entries
|
||||
are saved.
|
||||
If set to a value less than zero, the number of history entries is not
|
||||
limited.
|
||||
By default, the number of history entries is not limited.
|
||||
|
||||
@item horizontal-scroll-mode
|
||||
@vindex horizontal-scroll-mode
|
||||
|
@ -565,6 +579,22 @@ equivalent to @code{emacs-standard}. The default value is @code{emacs}.
|
|||
The value of the @code{editing-mode} variable also affects the
|
||||
default keymap.
|
||||
|
||||
@item keyseq-timeout
|
||||
Specifies the duration Readline will wait for a character when reading an
|
||||
ambiguous key sequence (one that can form a complete key sequence using
|
||||
the input read so far, or can take additional input to complete a longer
|
||||
key sequence).
|
||||
If no input is received within the timeout, Readline will use the shorter
|
||||
but complete key sequence.
|
||||
Readline uses this value to determine whether or not input is
|
||||
available on the current input source (@code{rl_instream} by default).
|
||||
The value is specified in milliseconds, so a value of 1000 means that
|
||||
Readline will wait one second for additional input.
|
||||
If this variable is set to a value less than or equal to zero, or to a
|
||||
non-numeric value, Readline will wait until another key is pressed to
|
||||
decide which key sequence to complete.
|
||||
The default value is @code{500}.
|
||||
|
||||
@item mark-directories
|
||||
If set to @samp{on}, completed directory names have a slash
|
||||
appended. The default is @samp{on}.
|
||||
|
@ -640,6 +670,13 @@ a common prefix) cause the matches to be listed immediately instead
|
|||
of ringing the bell.
|
||||
The default value is @samp{off}.
|
||||
|
||||
@item show-mode-in-prompt
|
||||
@vindex show-mode-in-prompt
|
||||
If set to @samp{on}, add a character to the beginning of the prompt
|
||||
indicating the editing mode: emacs (@samp{@@}), vi command (@samp{:}),
|
||||
or vi insertion (@samp{+}).
|
||||
The default value is @samp{off}.
|
||||
|
||||
@item skip-completed-text
|
||||
@vindex skip-completed-text
|
||||
If set to @samp{on}, this alters the default completion behavior when
|
||||
|
@ -880,7 +917,7 @@ binding, variable assignment, and conditional syntax.
|
|||
# You can re-read the inputrc file with C-x C-r.
|
||||
# Lines beginning with '#' are comments.
|
||||
#
|
||||
# First, include any systemwide bindings and variable
|
||||
# First, include any system-wide bindings and variable
|
||||
# assignments from /etc/Inputrc
|
||||
$include /etc/Inputrc
|
||||
|
||||
|
@ -1100,13 +1137,30 @@ for a string supplied by the user.
|
|||
@item history-search-forward ()
|
||||
Search forward through the history for the string of characters
|
||||
between the start of the current line and the point.
|
||||
The search string must match at the beginning of a history line.
|
||||
This is a non-incremental search.
|
||||
By default, this command is unbound.
|
||||
|
||||
@item history-search-backward ()
|
||||
Search backward through the history for the string of characters
|
||||
between the start of the current line and the point. This
|
||||
is a non-incremental search. By default, this command is unbound.
|
||||
between the start of the current line and the point.
|
||||
The search string must match at the beginning of a history line.
|
||||
This is a non-incremental search.
|
||||
By default, this command is unbound.
|
||||
|
||||
@item history-substr-search-forward ()
|
||||
Search forward through the history for the string of characters
|
||||
between the start of the current line and the point.
|
||||
The search string may match anywhere in a history line.
|
||||
This is a non-incremental search.
|
||||
By default, this command is unbound.
|
||||
|
||||
@item history-substr-search-backward ()
|
||||
Search backward through the history for the string of characters
|
||||
between the start of the current line and the point.
|
||||
The search string may match anywhere in a history line.
|
||||
This is a non-incremental search.
|
||||
By default, this command is unbound.
|
||||
|
||||
@item yank-nth-arg (M-C-y)
|
||||
Insert the first argument to the previous command (usually
|
||||
|
@ -1137,11 +1191,17 @@ as if the @samp{!$} history expansion had been specified.
|
|||
@subsection Commands For Changing Text
|
||||
|
||||
@ftable @code
|
||||
|
||||
@item @i{end-of-file} (usually C-d)
|
||||
The character indicating end-of-file as set, for example, by
|
||||
@code{stty}. If this character is read when there are no characters
|
||||
on the line, and point is at the beginning of the line, Readline
|
||||
interprets it as the end of input and returns @sc{eof}.
|
||||
|
||||
@item delete-char (C-d)
|
||||
Delete the character at point. If point is at the
|
||||
beginning of the line, there are no characters in the line, and
|
||||
the last character typed was not bound to @code{delete-char}, then
|
||||
return @sc{eof}.
|
||||
Delete the character at point. If this function is bound to the
|
||||
same character as the tty @sc{eof} character, as @kbd{C-d}
|
||||
commonly is, see above for the effects.
|
||||
|
||||
@item backward-delete-char (Rubout)
|
||||
Delete the character behind the cursor. A numeric argument means
|
||||
|
@ -1435,6 +1495,10 @@ and save the definition.
|
|||
Re-execute the last keyboard macro defined, by making the characters
|
||||
in the macro appear as if typed at the keyboard.
|
||||
|
||||
@item print-last-kbd-macro ()
|
||||
Print the last keboard macro defined in a format suitable for the
|
||||
@var{inputrc} file.
|
||||
|
||||
@end ftable
|
||||
|
||||
@node Miscellaneous Commands
|
||||
|
@ -1693,10 +1757,11 @@ When the command or function is invoked, the @env{COMP_LINE},
|
|||
assigned values as described above (@pxref{Bash Variables}).
|
||||
If a shell function is being invoked, the @env{COMP_WORDS} and
|
||||
@env{COMP_CWORD} variables are also set.
|
||||
When the function or command is invoked, the first argument is the
|
||||
When the function or command is invoked, the first argument ($1) is the
|
||||
name of the command whose arguments are being completed, the
|
||||
second argument is the word being completed, and the third argument
|
||||
is the word preceding the word being completed on the current command line.
|
||||
second argument ($2) is the word being completed, and the third argument
|
||||
($3) is the word preceding the word being completed on the current command
|
||||
line.
|
||||
No filtering of the generated completions against the word being completed
|
||||
is performed; the function or command has complete freedom in generating
|
||||
the matches.
|
||||
|
@ -1706,7 +1771,7 @@ The function may use any of the shell facilities, including the
|
|||
@code{compgen} and @code{compopt} builtins described below
|
||||
(@pxref{Programmable Completion Builtins}), to generate the matches.
|
||||
It must put the possible completions in the @env{COMPREPLY} array
|
||||
variable.
|
||||
variable, one per array element.
|
||||
|
||||
Next, any command specified with the @option{-C} option is invoked
|
||||
in an environment equivalent to command substitution.
|
||||
|
@ -1774,17 +1839,18 @@ completion function would load completions dynamically:
|
|||
@example
|
||||
_completion_loader()
|
||||
@{
|
||||
. "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124
|
||||
. "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124
|
||||
@}
|
||||
complete -D -F _completion_loader
|
||||
complete -D -F _completion_loader -o bashdefault -o default
|
||||
@end example
|
||||
|
||||
@node Programmable Completion Builtins
|
||||
@section Programmable Completion Builtins
|
||||
@cindex completion builtins
|
||||
|
||||
Two builtin commands are available to manipulate the programmable completion
|
||||
facilities.
|
||||
Three builtin commands are available to manipulate the programmable completion
|
||||
facilities: one to specify how the arguments to a particular command are to
|
||||
be completed, and two to modify the completion as it is happening.
|
||||
|
||||
@table @code
|
||||
@item compgen
|
||||
|
@ -1871,6 +1937,10 @@ quoting special characters, or suppressing trailing spaces).
|
|||
This option is intended to be used with shell functions specified
|
||||
with @option{-F}.
|
||||
|
||||
@item noquote
|
||||
Tell Readline not to quote the completed words if they are filenames
|
||||
(quoting filenames is the default).
|
||||
|
||||
@item nospace
|
||||
Tell Readline not to append a space (the default) to words completed at
|
||||
the end of the line.
|
||||
|
@ -1970,6 +2040,10 @@ used as the possible completions.
|
|||
@item -F @var{function}
|
||||
The shell function @var{function} is executed in the current shell
|
||||
environment.
|
||||
When it is executed, $1 is the name of the command whose arguments are
|
||||
being completed, $2 is the word being completed, and $3 is the word
|
||||
preceding the word being completed, as described above
|
||||
(@pxref{Programmable Completion}).
|
||||
When it finishes, the possible completions are retrieved from the value
|
||||
of the @env{COMPREPLY} array variable.
|
||||
|
||||
|
@ -2034,4 +2108,122 @@ specification exists, or an output error occurs.
|
|||
|
||||
@end table
|
||||
|
||||
@node A Programmable Completion Example
|
||||
@section A Programmable Completion Example
|
||||
|
||||
The most common way to obtain additional completion functionality beyond
|
||||
the default actions @code{complete} and @code{compgen} provide is to use
|
||||
a shell function and bind it to a particular command using @code{complete -F}.
|
||||
|
||||
The following function provides completions for the @code{cd} builtin.
|
||||
It is a reasonably good example of what shell functions must do when
|
||||
used for completion. This function uses the word passsed as @code{$2}
|
||||
to determine the directory name to complete. You can also use the
|
||||
@code{COMP_WORDS} array variable; the current word is indexed by the
|
||||
@code{COMP_CWORD} variable.
|
||||
|
||||
The function relies on the @code{complete} and @code{compgen} builtins
|
||||
to do much of the work, adding only the things that the Bash @code{cd}
|
||||
does beyond accepting basic directory names:
|
||||
tilde expansion (@pxref{Tilde Expansion}),
|
||||
searching directories in @var{$CDPATH}, which is described above
|
||||
(@pxref{Bourne Shell Builtins}),
|
||||
and basic support for the @code{cdable_vars} shell option
|
||||
(@pxref{The Shopt Builtin}).
|
||||
@code{_comp_cd} modifies the value of @var{IFS} so that it contains only
|
||||
a newline to accommodate file names containing spaces and tabs --
|
||||
@code{compgen} prints the possible completions it generates one per line.
|
||||
|
||||
Possible completions go into the @var{COMPREPLY} array variable, one
|
||||
completion per array element. The programmable completion system retrieves
|
||||
the completions from there when the function returns.
|
||||
|
||||
@example
|
||||
# A completion function for the cd builtin
|
||||
# based on the cd completion function from the bash_completion package
|
||||
_comp_cd()
|
||||
@{
|
||||
local IFS=$' \t\n' # normalize IFS
|
||||
local cur _skipdot _cdpath
|
||||
local i j k
|
||||
|
||||
# Tilde expansion, with side effect of expanding tilde to full pathname
|
||||
case "$2" in
|
||||
\~*) eval cur="$2" ;;
|
||||
*) cur=$2 ;;
|
||||
esac
|
||||
|
||||
# no cdpath or absolute pathname -- straight directory completion
|
||||
if [[ -z "$@{CDPATH:-@}" ]] || [[ "$cur" == @@(./*|../*|/*) ]]; then
|
||||
# compgen prints paths one per line; could also use while loop
|
||||
IFS=$'\n'
|
||||
COMPREPLY=( $(compgen -d -- "$cur") )
|
||||
IFS=$' \t\n'
|
||||
# CDPATH+directories in the current directory if not in CDPATH
|
||||
else
|
||||
IFS=$'\n'
|
||||
_skipdot=false
|
||||
# preprocess CDPATH to convert null directory names to .
|
||||
_cdpath=$@{CDPATH/#:/.:@}
|
||||
_cdpath=$@{_cdpath//::/:.:@}
|
||||
_cdpath=$@{_cdpath/%:/:.@}
|
||||
for i in $@{_cdpath//:/$'\n'@}; do
|
||||
if [[ $i -ef . ]]; then _skipdot=true; fi
|
||||
k="$@{#COMPREPLY[@@]@}"
|
||||
for j in $( compgen -d -- "$i/$cur" ); do
|
||||
COMPREPLY[k++]=$@{j#$i/@} # cut off directory
|
||||
done
|
||||
done
|
||||
$_skipdot || COMPREPLY+=( $(compgen -d -- "$cur") )
|
||||
IFS=$' \t\n'
|
||||
fi
|
||||
|
||||
# variable names if appropriate shell option set and no completions
|
||||
if shopt -q cdable_vars && [[ $@{#COMPREPLY[@@]@} -eq 0 ]]; then
|
||||
COMPREPLY=( $(compgen -v -- "$cur") )
|
||||
fi
|
||||
|
||||
return 0
|
||||
@}
|
||||
@end example
|
||||
|
||||
We install the completion function using the @option{-F} option to
|
||||
@code{complete}:
|
||||
|
||||
@example
|
||||
# Tell readline to quote appropriate and append slashes to directories;
|
||||
# use the bash default completion for other arguments
|
||||
complete -o filenames -o nospace -o bashdefault -F _comp_cd cd
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
Since we'd like Bash and Readline to take care of some
|
||||
of the other details for us, we use several other options to tell Bash
|
||||
and Readline what to do. The @option{-o filenames} option tells Readline
|
||||
that the possible completions should be treated as filenames, and quoted
|
||||
appropriately. That option will also cause Readline to append a slash to
|
||||
filenames it can determine are directories (which is why we might want to
|
||||
extend @code{_comp_cd} to append a slash if we're using directories found
|
||||
via @var{CDPATH}: Readline can't tell those completions are directories).
|
||||
The @option{-o nospace} option tells Readline to not append a space
|
||||
character to the directory name, in case we want to append to it.
|
||||
The @option{-o bashdefault} option brings in the rest of the "Bash default"
|
||||
completions -- possible completion that Bash adds to the default Readline
|
||||
set. These include things like command name completion, variable completion
|
||||
for words beginning with @samp{@{}, completions containing pathname
|
||||
expansion patterns (@pxref{Filename Expansion}), and so on.
|
||||
|
||||
Once installed using @code{complete}, @code{_comp_cd} will be called every
|
||||
time we attempt word completion for a @code{cd} command.
|
||||
|
||||
Many more examples -- an extensive collection of completions for most of
|
||||
the common GNU, Unix, and Linux commands -- are available as part of the
|
||||
bash_completion project. This is installed by default on many GNU/Linux
|
||||
distributions. Originally written by Ian Macdonald, the project now lives
|
||||
at @url{http://bash-completion.alioth.debian.org/}. There are ports for
|
||||
other systems such as Solaris and Mac OS X.
|
||||
|
||||
An older version of the bash_completion package is distributed with bash
|
||||
in the @file{examples/complete} subdirectory.
|
||||
|
||||
@end ifset
|
||||
|
|
|
@ -2,33 +2,25 @@
|
|||
@comment %**start of header (This is for running Texinfo on a region.)
|
||||
@setfilename rluserman.info
|
||||
@settitle GNU Readline Library
|
||||
@comment %**end of header (This is for running Texinfo on a region.)
|
||||
|
||||
@include version.texi
|
||||
|
||||
@comment %**end of header (This is for running Texinfo on a region.)
|
||||
|
||||
@copying
|
||||
This manual describes the end user interface of the GNU Readline Library
|
||||
(version @value{VERSION}, @value{UPDATED}), a library which aids in the
|
||||
consistency of user interface across discrete programs which provide
|
||||
a command line interface.
|
||||
|
||||
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
|
||||
are preserved on all copies.
|
||||
Copyright @copyright{} 1988--2014 Free Software Foundation, Inc.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with the Front-Cover texts being ``A GNU Manual'',
|
||||
and with the Back-Cover Texts as in (a) below. A copy of the license is
|
||||
included in the section entitled ``GNU Free Documentation License''.
|
||||
|
||||
(a) The FSF's Back-Cover Text is: You are free to copy and modify
|
||||
this GNU manual. Buying copies from GNU Press supports the FSF in
|
||||
developing GNU and promoting software freedom.''
|
||||
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
|
||||
A copy of the license is included in the section entitled
|
||||
``GNU Free Documentation License''.
|
||||
|
||||
@end quotation
|
||||
@end copying
|
||||
|
@ -49,12 +41,6 @@ developing GNU and promoting software freedom.''
|
|||
@vskip 0pt plus 1filll
|
||||
@insertcopying
|
||||
|
||||
@sp 1
|
||||
Published by the Free Software Foundation @*
|
||||
59 Temple Place, Suite 330, @*
|
||||
Boston, MA 02111-1307 @*
|
||||
USA @*
|
||||
|
||||
@end titlepage
|
||||
|
||||
@contents
|
||||
|
@ -66,6 +52,7 @@ USA @*
|
|||
This document describes the end user interface of the GNU Readline Library,
|
||||
a utility which aids in the consistency of user interface across discrete
|
||||
programs which provide a command line interface.
|
||||
The Readline home page is @url{http://www.gnu.org/software/readline/}.
|
||||
|
||||
@menu
|
||||
* Command Line Editing:: GNU Readline User's Manual.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
@ignore
|
||||
Copyright (C) 1988-2011 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2014 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set EDITION 6.2
|
||||
@set VERSION 6.2
|
||||
@set UPDATED September 6 2010
|
||||
@set UPDATED-MONTH September 2010
|
||||
@set EDITION 6.3
|
||||
@set VERSION 6.3
|
||||
@set UPDATED 6 January 2014
|
||||
@set UPDATED-MONTH January 2014
|
||||
|
||||
@set LASTCHANGE Mon Sep 6 22:07:10 EDT 2010
|
||||
@set LASTCHANGE Mon Jan 6 16:26:51 EST 2014
|
||||
|
|
|
@ -40,13 +40,14 @@ Copyright (C) 1999 Jeff Solomon
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <termios.h> /* xxx - should make this more general */
|
||||
|
||||
#ifdef READLINE_LIBRARY
|
||||
|
@ -55,6 +56,10 @@ Copyright (C) 1999 Jeff Solomon
|
|||
# include <readline/readline.h>
|
||||
#endif
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
# define STDIN_FILENO 0
|
||||
#endif
|
||||
|
||||
/* This little examples demonstrates the alternate interface to using readline.
|
||||
* In the alternate interface, the user maintains control over program flow and
|
||||
* only calls readline when STDIN is readable. Using the alternate interface,
|
||||
|
|
81
lib/readline/examples/rl-callbacktest.c
Normal file
81
lib/readline/examples/rl-callbacktest.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* Standard include files. stdio.h is required. */
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Used for select(2) */
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Standard readline include files. */
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
static void cb_linehandler (char *);
|
||||
|
||||
int running;
|
||||
const char *prompt = "rltest$ ";
|
||||
|
||||
/* Callback function called for each line when accept-line executed, EOF
|
||||
seen, or EOF character read. This sets a flag and returns; it could
|
||||
also call exit(3). */
|
||||
static void
|
||||
cb_linehandler (char *line)
|
||||
{
|
||||
/* Can use ^D (stty eof) or `exit' to exit. */
|
||||
if (line == NULL || strcmp (line, "exit") == 0)
|
||||
{
|
||||
if (line == 0)
|
||||
printf ("\n");
|
||||
printf ("exit\n");
|
||||
/* This function needs to be called to reset the terminal settings,
|
||||
and calling it from the line handler keeps one extra prompt from
|
||||
being displayed. */
|
||||
rl_callback_handler_remove ();
|
||||
|
||||
running = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*line)
|
||||
add_history (line);
|
||||
printf ("input line: %s\n", line);
|
||||
free (line);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int c, char **v)
|
||||
{
|
||||
fd_set fds;
|
||||
int r;
|
||||
|
||||
/* Install the line handler. */
|
||||
rl_callback_handler_install (prompt, cb_linehandler);
|
||||
|
||||
/* Enter a simple event loop. This waits until something is available
|
||||
to read on readline's input stream (defaults to standard input) and
|
||||
calls the builtin character read callback to read it. It does not
|
||||
have to modify the user's terminal settings. */
|
||||
running = 1;
|
||||
while (running)
|
||||
{
|
||||
FD_ZERO (&fds);
|
||||
FD_SET (fileno (rl_instream), &fds);
|
||||
|
||||
r = select (FD_SETSIZE, &fds, NULL, NULL, NULL);
|
||||
if (r < 0)
|
||||
{
|
||||
perror ("rltest: select");
|
||||
rl_callback_handler_remove ();
|
||||
break;
|
||||
}
|
||||
|
||||
if (FD_ISSET (fileno (rl_instream), &fds))
|
||||
rl_callback_read_char ();
|
||||
}
|
||||
|
||||
printf ("rltest: Event loop has exited\n");
|
||||
return 0;
|
||||
}
|
|
@ -98,6 +98,8 @@ static const FUNMAP default_funmap[] = {
|
|||
{ "forward-word", rl_forward_word },
|
||||
{ "history-search-backward", rl_history_search_backward },
|
||||
{ "history-search-forward", rl_history_search_forward },
|
||||
{ "history-substring-search-backward", rl_history_substr_search_backward },
|
||||
{ "history-substring-search-forward", rl_history_substr_search_forward },
|
||||
{ "insert-comment", rl_insert_comment },
|
||||
{ "insert-completions", rl_insert_completions },
|
||||
{ "kill-whole-line", rl_kill_full_line },
|
||||
|
@ -118,6 +120,7 @@ static const FUNMAP default_funmap[] = {
|
|||
#endif
|
||||
{ "possible-completions", rl_possible_completions },
|
||||
{ "previous-history", rl_get_previous_history },
|
||||
{ "print-last-kbd-macro", rl_print_last_kbd_macro },
|
||||
{ "quoted-insert", rl_quoted_insert },
|
||||
{ "re-read-init-file", rl_re_read_init_file },
|
||||
{ "redraw-current-line", rl_refresh_line},
|
||||
|
@ -236,7 +239,7 @@ rl_initialize_funmap ()
|
|||
|
||||
/* Produce a NULL terminated array of known function names. The array
|
||||
is sorted. The array itself is allocated, but not the strings inside.
|
||||
You should free () the array when you done, but not the pointrs. */
|
||||
You should free () the array when you done, but not the pointers. */
|
||||
const char **
|
||||
rl_funmap_names ()
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* histexpand.c -- history expansion. */
|
||||
|
||||
/* Copyright (C) 1989-2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (History), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
|
@ -272,6 +272,8 @@ get_history_event (string, caller_index, delimiting_quote)
|
|||
if (local_index == 0 || substring_okay)
|
||||
{
|
||||
entry = current_history ();
|
||||
if (entry == 0)
|
||||
FAIL_SEARCH ();
|
||||
history_offset = history_length;
|
||||
|
||||
/* If this was a substring search, then remember the
|
||||
|
@ -519,9 +521,9 @@ postproc_subst_rhs ()
|
|||
the returned string. Returns the new index into string in
|
||||
*END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
|
||||
static int
|
||||
history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
|
||||
history_expand_internal (string, start, qc, end_index_ptr, ret_string, current_line)
|
||||
char *string;
|
||||
int start, *end_index_ptr;
|
||||
int start, qc, *end_index_ptr;
|
||||
char **ret_string;
|
||||
char *current_line; /* for !# */
|
||||
{
|
||||
|
@ -557,30 +559,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
|
|||
event = current_line;
|
||||
}
|
||||
else
|
||||
{
|
||||
int quoted_search_delimiter = 0;
|
||||
|
||||
/* If the character before this `!' is a double or single
|
||||
quote, then this expansion takes place inside of the
|
||||
quoted string. If we have to search for some text ("!foo"),
|
||||
allow the delimiter to end the search string. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
int ch, l;
|
||||
l = _rl_find_prev_mbchar (string, i, MB_FIND_ANY);
|
||||
ch = string[l];
|
||||
/* XXX - original patch had i - 1 ??? If i == 0 it would fail. */
|
||||
if (i && (ch == '\'' || ch == '"'))
|
||||
quoted_search_delimiter = ch;
|
||||
}
|
||||
else
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
if (i && (string[i - 1] == '\'' || string[i - 1] == '"'))
|
||||
quoted_search_delimiter = string[i - 1];
|
||||
|
||||
event = get_history_event (string, &i, quoted_search_delimiter);
|
||||
}
|
||||
event = get_history_event (string, &i, qc);
|
||||
|
||||
if (event == 0)
|
||||
{
|
||||
|
@ -854,7 +833,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
|
|||
}
|
||||
i += 2;
|
||||
}
|
||||
/* Done with modfiers. */
|
||||
/* Done with modifiers. */
|
||||
/* Believe it or not, we have to back the pointer up by one. */
|
||||
--i;
|
||||
|
||||
|
@ -928,7 +907,7 @@ history_expand (hstring, output)
|
|||
char **output;
|
||||
{
|
||||
register int j;
|
||||
int i, r, l, passc, cc, modified, eindex, only_printing, dquote, flag;
|
||||
int i, r, l, passc, cc, modified, eindex, only_printing, dquote, squote, flag;
|
||||
char *string;
|
||||
|
||||
/* The output string, and its length. */
|
||||
|
@ -991,7 +970,7 @@ history_expand (hstring, output)
|
|||
|
||||
/* `!' followed by one of the characters in history_no_expand_chars
|
||||
is NOT an expansion. */
|
||||
for (i = dquote = 0; string[i]; i++)
|
||||
for (i = dquote = squote = 0; string[i]; i++)
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
|
@ -1022,6 +1001,13 @@ history_expand (hstring, output)
|
|||
{
|
||||
if (cc == 0 || member (cc, history_no_expand_chars))
|
||||
continue;
|
||||
/* DQUOTE won't be set unless history_quotes_inhibit_expansion
|
||||
is set. The idea here is to treat double-quoted strings the
|
||||
same as the word outside double quotes; in effect making the
|
||||
double quote part of history_no_expand_chars when DQUOTE is
|
||||
set. */
|
||||
else if (dquote && cc == '"')
|
||||
continue;
|
||||
/* If the calling application has set
|
||||
history_inhibit_expansion_function to a function that checks
|
||||
for special cases that should not be history expanded,
|
||||
|
@ -1071,9 +1057,9 @@ history_expand (hstring, output)
|
|||
}
|
||||
|
||||
/* Extract and perform the substitution. */
|
||||
for (passc = dquote = i = j = 0; i < l; i++)
|
||||
for (passc = dquote = squote = i = j = 0; i < l; i++)
|
||||
{
|
||||
int tchar = string[i];
|
||||
int qc, tchar = string[i];
|
||||
|
||||
if (passc)
|
||||
{
|
||||
|
@ -1130,8 +1116,14 @@ history_expand (hstring, output)
|
|||
case '\'':
|
||||
{
|
||||
/* If history_quotes_inhibit_expansion is set, single quotes
|
||||
inhibit history expansion. */
|
||||
if (dquote == 0 && history_quotes_inhibit_expansion)
|
||||
inhibit history expansion, otherwise they are treated like
|
||||
double quotes. */
|
||||
if (squote)
|
||||
{
|
||||
squote = 0;
|
||||
ADD_CHAR (tchar);
|
||||
}
|
||||
else if (dquote == 0 && history_quotes_inhibit_expansion)
|
||||
{
|
||||
int quote, slen;
|
||||
|
||||
|
@ -1146,6 +1138,11 @@ history_expand (hstring, output)
|
|||
ADD_STRING (temp);
|
||||
xfree (temp);
|
||||
}
|
||||
else if (dquote == 0 && squote == 0 && history_quotes_inhibit_expansion == 0)
|
||||
{
|
||||
squote = 1;
|
||||
ADD_CHAR (string[i]);
|
||||
}
|
||||
else
|
||||
ADD_CHAR (string[i]);
|
||||
break;
|
||||
|
@ -1171,6 +1168,7 @@ history_expand (hstring, output)
|
|||
characters in history_no_expand_chars, then it is not a
|
||||
candidate for expansion of any kind. */
|
||||
if (cc == 0 || member (cc, history_no_expand_chars) ||
|
||||
(dquote && cc == '"') ||
|
||||
(history_inhibit_expansion_function && (*history_inhibit_expansion_function) (string, i)))
|
||||
{
|
||||
ADD_CHAR (string[i]);
|
||||
|
@ -1196,8 +1194,8 @@ history_expand (hstring, output)
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
r = history_expand_internal (string, i, &eindex, &temp, result);
|
||||
qc = squote ? '\'' : (dquote ? '"' : 0);
|
||||
r = history_expand_internal (string, i, qc, &eindex, &temp, result);
|
||||
if (r < 0)
|
||||
{
|
||||
*output = temp;
|
||||
|
|
|
@ -125,14 +125,7 @@ history_filename (filename)
|
|||
home = sh_get_env_value ("HOME");
|
||||
|
||||
if (home == 0)
|
||||
{
|
||||
#if 0
|
||||
home = ".";
|
||||
home_len = 1;
|
||||
#else
|
||||
return (NULL);
|
||||
#endif
|
||||
}
|
||||
return (NULL);
|
||||
else
|
||||
home_len = strlen (home);
|
||||
|
||||
|
@ -148,6 +141,21 @@ history_filename (filename)
|
|||
return (return_val);
|
||||
}
|
||||
|
||||
static char *
|
||||
history_backupfile (filename)
|
||||
const char *filename;
|
||||
{
|
||||
char *ret;
|
||||
size_t len;
|
||||
|
||||
len = strlen (filename);
|
||||
ret = xmalloc (len + 2);
|
||||
strcpy (ret, filename);
|
||||
ret[len] = '-';
|
||||
ret[len+1] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Add the contents of FILENAME to the history list, a line at a time.
|
||||
If FILENAME is NULL, then read from ~/.history. Returns 0 if
|
||||
successful, or errno if not. */
|
||||
|
@ -403,14 +411,16 @@ history_truncate_file (fname, lines)
|
|||
truncate to. */
|
||||
if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
|
||||
{
|
||||
write (file, bp, chars_read - (bp - buffer));
|
||||
if (write (file, bp, chars_read - (bp - buffer)) < 0)
|
||||
rv = errno;
|
||||
|
||||
#if defined (__BEOS__)
|
||||
/* BeOS ignores O_TRUNC. */
|
||||
ftruncate (file, chars_read - (bp - buffer));
|
||||
#endif
|
||||
|
||||
close (file);
|
||||
if (close (file) < 0 && rv == 0)
|
||||
rv = errno;
|
||||
}
|
||||
|
||||
truncate_exit:
|
||||
|
@ -430,7 +440,7 @@ history_do_write (filename, nelements, overwrite)
|
|||
int nelements, overwrite;
|
||||
{
|
||||
register int i;
|
||||
char *output;
|
||||
char *output, *bakname;
|
||||
int file, mode, rv;
|
||||
#ifdef HISTORY_USE_MMAP
|
||||
size_t cursize;
|
||||
|
@ -440,13 +450,22 @@ 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);
|
||||
bakname = (overwrite && output) ? history_backupfile (output) : 0;
|
||||
|
||||
if (output && bakname)
|
||||
rename (output, bakname);
|
||||
|
||||
file = output ? open (output, mode, 0600) : -1;
|
||||
rv = 0;
|
||||
|
||||
if (file == -1)
|
||||
{
|
||||
rv = errno;
|
||||
if (output && bakname)
|
||||
rename (bakname, output);
|
||||
FREE (output);
|
||||
return (errno);
|
||||
FREE (bakname);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
#ifdef HISTORY_USE_MMAP
|
||||
|
@ -486,8 +505,11 @@ history_do_write (filename, nelements, overwrite)
|
|||
{
|
||||
mmap_error:
|
||||
rv = errno;
|
||||
FREE (output);
|
||||
close (file);
|
||||
if (output && bakname)
|
||||
rename (bakname, output);
|
||||
FREE (output);
|
||||
FREE (bakname);
|
||||
return rv;
|
||||
}
|
||||
#else
|
||||
|
@ -495,8 +517,11 @@ mmap_error:
|
|||
if (buffer == 0)
|
||||
{
|
||||
rv = errno;
|
||||
FREE (output);
|
||||
close (file);
|
||||
if (output && bakname)
|
||||
rename (bakname, output);
|
||||
FREE (output);
|
||||
FREE (bakname);
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
@ -524,9 +549,16 @@ mmap_error:
|
|||
#endif
|
||||
}
|
||||
|
||||
close (file);
|
||||
if (close (file) < 0 && rv == 0)
|
||||
rv = errno;
|
||||
|
||||
if (rv != 0 && output && bakname)
|
||||
rename (bakname, output);
|
||||
else if (rv == 0 && bakname)
|
||||
unlink (bakname);
|
||||
|
||||
FREE (output);
|
||||
FREE (bakname);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* history.c -- standalone history library */
|
||||
|
||||
/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2011 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (History), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
|
@ -236,7 +236,7 @@ history_get_time (hist)
|
|||
ts = hist->timestamp;
|
||||
if (ts[0] != history_comment_char)
|
||||
return 0;
|
||||
t = (time_t) atol (ts + 1); /* XXX - should use strtol() here */
|
||||
t = (time_t) strtol (ts + 1, (char **)NULL, 10); /* XXX - should use strtol() here */
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -318,7 +318,7 @@ add_history_time (string)
|
|||
{
|
||||
HIST_ENTRY *hs;
|
||||
|
||||
if (string == 0)
|
||||
if (string == 0 || history_length < 1)
|
||||
return;
|
||||
hs = the_history[history_length - 1];
|
||||
FREE (hs->timestamp);
|
||||
|
@ -394,7 +394,7 @@ replace_history_entry (which, line, data)
|
|||
WHICH >= 0 means to replace that particular history entry's data, as
|
||||
long as it matches OLD. */
|
||||
void
|
||||
replace_history_data (which,old, new)
|
||||
replace_history_data (which, old, new)
|
||||
int which;
|
||||
histdata_t *old, *new;
|
||||
{
|
||||
|
|
|
@ -216,7 +216,7 @@ extern int history_truncate_file PARAMS((const char *, int));
|
|||
-1) If there was an error in expansion.
|
||||
2) If the returned line should just be printed.
|
||||
|
||||
If an error ocurred in expansion, then OUTPUT contains a descriptive
|
||||
If an error occurred in expansion, then OUTPUT contains a descriptive
|
||||
error message. */
|
||||
extern int history_expand PARAMS((char *, char **));
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* input.c -- character input functions for readline. */
|
||||
|
||||
/* Copyright (C) 1994-2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1994-2013 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.
|
||||
|
@ -45,6 +45,8 @@
|
|||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "posixselect.h"
|
||||
|
||||
#if defined (FIONREAD_IN_SYS_IOCTL)
|
||||
|
@ -78,6 +80,13 @@ extern int errno;
|
|||
character input. */
|
||||
rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL;
|
||||
|
||||
/* A function to call if a read(2) is interrupted by a signal. */
|
||||
rl_hook_func_t *rl_signal_event_hook = (rl_hook_func_t *)NULL;
|
||||
|
||||
/* A function to replace _rl_input_available for applications using the
|
||||
callback interface. */
|
||||
rl_hook_func_t *rl_input_available_hook = (rl_hook_func_t *)NULL;
|
||||
|
||||
rl_getc_func_t *rl_getc_function = rl_getc;
|
||||
|
||||
static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */
|
||||
|
@ -104,6 +113,12 @@ _rl_any_typein ()
|
|||
return any_typein;
|
||||
}
|
||||
|
||||
int
|
||||
_rl_pushed_input_available ()
|
||||
{
|
||||
return (push_index != pop_index);
|
||||
}
|
||||
|
||||
/* Return the amount of space available in the buffer for stuffing
|
||||
characters. */
|
||||
static int
|
||||
|
@ -117,7 +132,7 @@ ibuffer_space ()
|
|||
|
||||
/* Get a key from the buffer of characters to be read.
|
||||
Return the key in KEY.
|
||||
Result is KEY if there was a key, or 0 if there wasn't. */
|
||||
Result is non-zero if there was a key, or 0 if there wasn't. */
|
||||
static int
|
||||
rl_get_char (key)
|
||||
int *key;
|
||||
|
@ -154,12 +169,6 @@ _rl_unget_char (key)
|
|||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
_rl_pushed_input_available ()
|
||||
{
|
||||
return (push_index != pop_index);
|
||||
}
|
||||
|
||||
/* If a character is available to be read, then read it and stuff it into
|
||||
IBUFFER. Otherwise, just return. Returns number of characters read
|
||||
(0 if none available) and -1 on error (EIO). */
|
||||
|
@ -291,6 +300,9 @@ _rl_input_available ()
|
|||
#endif
|
||||
int tty;
|
||||
|
||||
if (rl_input_available_hook)
|
||||
return (*rl_input_available_hook) ();
|
||||
|
||||
tty = fileno (rl_instream);
|
||||
|
||||
#if defined (HAVE_SELECT)
|
||||
|
@ -411,8 +423,6 @@ rl_read_key ()
|
|||
{
|
||||
int c, r;
|
||||
|
||||
rl_key_sequence_length++;
|
||||
|
||||
if (rl_pending_input)
|
||||
{
|
||||
c = rl_pending_input;
|
||||
|
@ -437,7 +447,7 @@ rl_read_key ()
|
|||
rl_done = 1;
|
||||
return ('\n');
|
||||
}
|
||||
else if (r == 1) /* read something */
|
||||
else if (r > 0) /* read something */
|
||||
continue;
|
||||
|
||||
RL_CHECK_SIGNALS ();
|
||||
|
@ -450,6 +460,7 @@ rl_read_key ()
|
|||
{
|
||||
if (rl_get_char (&c) == 0)
|
||||
c = (*rl_getc_function) (rl_instream);
|
||||
/* fprintf(stderr, "rl_read_key: calling RL_CHECK_SIGNALS: _rl_caught_signal = %d", _rl_caught_signal); */
|
||||
RL_CHECK_SIGNALS ();
|
||||
}
|
||||
}
|
||||
|
@ -468,6 +479,8 @@ rl_getc (stream)
|
|||
{
|
||||
RL_CHECK_SIGNALS ();
|
||||
|
||||
/* We know at this point that _rl_caught_signal == 0 */
|
||||
|
||||
#if defined (__MINGW32__)
|
||||
if (isatty (fileno (stream)))
|
||||
return (getch ());
|
||||
|
@ -509,11 +522,23 @@ rl_getc (stream)
|
|||
#undef X_EWOULDBLOCK
|
||||
#undef X_EAGAIN
|
||||
|
||||
/* If the error that we received was SIGINT, then try again,
|
||||
this is simply an interrupted system call to read ().
|
||||
Otherwise, some error ocurred, also signifying EOF. */
|
||||
/* fprintf(stderr, "rl_getc: result = %d errno = %d\n", result, errno); */
|
||||
|
||||
/* If the error that we received was EINTR, then try again,
|
||||
this is simply an interrupted system call to read (). We allow
|
||||
the read to be interrupted if we caught SIGHUP or SIGTERM (but
|
||||
not SIGINT; let the signal handler deal with that), but if the
|
||||
application sets an event hook, call it for other signals.
|
||||
Otherwise (not EINTR), some error occurred, also signifying EOF. */
|
||||
if (errno != EINTR)
|
||||
return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF);
|
||||
else if (_rl_caught_signal == SIGHUP || _rl_caught_signal == SIGTERM)
|
||||
return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF);
|
||||
else if (_rl_caught_signal == SIGINT || _rl_caught_signal == SIGQUIT)
|
||||
RL_CHECK_SIGNALS ();
|
||||
|
||||
if (rl_signal_event_hook)
|
||||
(*rl_signal_event_hook) ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2012 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.
|
||||
|
@ -110,7 +110,7 @@ _rl_scxt_alloc (type, flags)
|
|||
cxt->history_pos = 0;
|
||||
cxt->direction = 0;
|
||||
|
||||
cxt->lastc = 0;
|
||||
cxt->prevc = cxt->lastc = 0;
|
||||
|
||||
cxt->sline = 0;
|
||||
cxt->sline_len = cxt->sline_index = 0;
|
||||
|
@ -156,16 +156,16 @@ rl_forward_search_history (sign, key)
|
|||
WHERE is the history list number of the current line. If it is
|
||||
-1, then this line is the starting one. */
|
||||
static void
|
||||
rl_display_search (search_string, reverse_p, where)
|
||||
rl_display_search (search_string, flags, where)
|
||||
char *search_string;
|
||||
int reverse_p, where;
|
||||
int flags, where;
|
||||
{
|
||||
char *message;
|
||||
int msglen, searchlen;
|
||||
|
||||
searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
|
||||
|
||||
message = (char *)xmalloc (searchlen + 33);
|
||||
message = (char *)xmalloc (searchlen + 64);
|
||||
msglen = 0;
|
||||
|
||||
#if defined (NOTDEF)
|
||||
|
@ -178,7 +178,13 @@ rl_display_search (search_string, reverse_p, where)
|
|||
|
||||
message[msglen++] = '(';
|
||||
|
||||
if (reverse_p)
|
||||
if (flags & SF_FAILED)
|
||||
{
|
||||
strcpy (message + msglen, "failed ");
|
||||
msglen += 7;
|
||||
}
|
||||
|
||||
if (flags & SF_REVERSE)
|
||||
{
|
||||
strcpy (message + msglen, "reverse-");
|
||||
msglen += 8;
|
||||
|
@ -215,7 +221,7 @@ _rl_isearch_init (direction)
|
|||
cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
|
||||
: default_isearch_terminators;
|
||||
|
||||
/* Create an arrary of pointers to the lines that we want to search. */
|
||||
/* Create an array of pointers to the lines that we want to search. */
|
||||
hlist = history_list ();
|
||||
rl_maybe_replace_line ();
|
||||
i = 0;
|
||||
|
@ -312,13 +318,19 @@ _rl_search_getchar (cxt)
|
|||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* This ends up with C (and LASTC) being set to the last byte of the
|
||||
multibyte character. In most cases c == lastc == mb[0] */
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
|
||||
#endif
|
||||
|
||||
RL_CHECK_SIGNALS ();
|
||||
return c;
|
||||
}
|
||||
|
||||
#define ENDSRCH_CHAR(c) \
|
||||
((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
|
||||
|
||||
/* Process just-read character C according to isearch context CXT. Return
|
||||
-1 if the caller should just free the context and return, 0 if we should
|
||||
break out of the loop, and 1 if we should continue to read characters. */
|
||||
|
@ -344,13 +356,43 @@ _rl_isearch_dispatch (cxt, c)
|
|||
incremental search, so we check */
|
||||
if (c >= 0 && cxt->keymap[c].type == ISKMAP && strchr (cxt->search_terminators, cxt->lastc) == 0)
|
||||
{
|
||||
/* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
|
||||
takes microseconds, so multiply by 1000. If we don't get any
|
||||
additional input and this keymap shadows another function, process
|
||||
that key as if it was all we read. */
|
||||
if (_rl_keyseq_timeout > 0 &&
|
||||
RL_ISSTATE (RL_STATE_CALLBACK) == 0 &&
|
||||
RL_ISSTATE (RL_STATE_INPUTPENDING) == 0 &&
|
||||
_rl_pushed_input_available () == 0 &&
|
||||
((Keymap)(cxt->keymap[c].function))[ANYOTHERKEY].function &&
|
||||
_rl_input_queued (_rl_keyseq_timeout*1000) == 0)
|
||||
goto add_character;
|
||||
|
||||
cxt->okeymap = cxt->keymap;
|
||||
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. */
|
||||
something useful if this doesn't end up mapping to a command we
|
||||
interpret here. Right now we just save the most recent character
|
||||
that caused the index into a new keymap. */
|
||||
cxt->prevc = c;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
if (cxt->mb[1] == 0)
|
||||
{
|
||||
cxt->pmb[0] = c; /* XXX should be == cxt->mb[0] */
|
||||
cxt->pmb[1] = '\0';
|
||||
}
|
||||
else
|
||||
memcpy (cxt->pmb, cxt->mb, sizeof (cxt->pmb));
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
add_character:
|
||||
|
||||
/* Translate the keys we do something with to opcodes. */
|
||||
if (c >= 0 && cxt->keymap[c].type == ISFUNC)
|
||||
{
|
||||
|
@ -376,6 +418,54 @@ _rl_isearch_dispatch (cxt, c)
|
|||
{
|
||||
cxt->keymap = cxt->okeymap;
|
||||
cxt->sflags &= ~SF_CHGKMAP;
|
||||
/* If we indexed into a new keymap, but didn't map to a command that
|
||||
affects the search (lastc > 0), and the character that mapped to a
|
||||
new keymap would have ended the search (ENDSRCH_CHAR(cxt->prevc)),
|
||||
handle that now as if the previous char would have ended the search
|
||||
and we would have read the current character. */
|
||||
/* XXX - should we check cxt->mb? */
|
||||
if (cxt->lastc > 0 && ENDSRCH_CHAR (cxt->prevc))
|
||||
{
|
||||
rl_stuff_char (cxt->lastc);
|
||||
rl_execute_next (cxt->prevc);
|
||||
/* XXX - do we insert everything in cxt->pmb? */
|
||||
return (0);
|
||||
}
|
||||
/* Otherwise, if the current character is mapped to self-insert or
|
||||
nothing (i.e., not an editing command), and the previous character
|
||||
was a keymap index, then we need to insert both the previous
|
||||
character and the current character into the search string. */
|
||||
else if (cxt->lastc > 0 && cxt->prevc > 0 &&
|
||||
cxt->keymap[cxt->prevc].type == ISKMAP &&
|
||||
(f == 0 || f == rl_insert))
|
||||
{
|
||||
/* Make lastc be the next character read */
|
||||
/* XXX - do we insert everything in cxt->mb? */
|
||||
rl_execute_next (cxt->lastc);
|
||||
/* Dispatch on the previous character (insert into search string) */
|
||||
cxt->lastc = cxt->prevc;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* Have to overwrite cxt->mb here because dispatch uses it below */
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
if (cxt->pmb[1] == 0)
|
||||
{
|
||||
cxt->mb[0] = cxt->lastc; /* == cxt->prevc */
|
||||
cxt->mb[1] = '\0';
|
||||
}
|
||||
else
|
||||
memcpy (cxt->mb, cxt->pmb, sizeof (cxt->mb));
|
||||
}
|
||||
#endif
|
||||
cxt->prevc = 0;
|
||||
}
|
||||
else if (cxt->lastc > 0 && cxt->prevc > 0 && f && f != rl_insert)
|
||||
{
|
||||
rl_stuff_char (cxt->lastc);
|
||||
rl_execute_next (cxt->prevc);
|
||||
/* XXX - do we insert everything in cxt->pmb? */
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* The characters in isearch_terminators (set from the user-settable
|
||||
|
@ -393,14 +483,11 @@ _rl_isearch_dispatch (cxt, c)
|
|||
XXX - since _rl_input_available depends on the application-
|
||||
settable keyboard timeout value, this could alternatively
|
||||
use _rl_input_queued(100000) */
|
||||
if (cxt->lastc == ESC && _rl_input_available ())
|
||||
if (cxt->lastc == ESC && (_rl_pushed_input_available () || _rl_input_available ()))
|
||||
rl_execute_next (ESC);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define ENDSRCH_CHAR(c) \
|
||||
((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
|
@ -436,7 +523,7 @@ _rl_isearch_dispatch (cxt, c)
|
|||
cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
|
||||
strcpy (cxt->search_string, last_isearch_string);
|
||||
cxt->search_string_index = last_isearch_string_len;
|
||||
rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1);
|
||||
rl_display_search (cxt->search_string, cxt->sflags, -1);
|
||||
break;
|
||||
}
|
||||
return (1);
|
||||
|
@ -544,12 +631,16 @@ _rl_isearch_dispatch (cxt, c)
|
|||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
int j, l;
|
||||
for (j = 0, l = strlen (cxt->mb); j < l; )
|
||||
cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
|
||||
|
||||
if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
|
||||
cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
|
||||
else
|
||||
for (j = 0, l = RL_STRLEN (cxt->mb); j < l; )
|
||||
cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
cxt->search_string[cxt->search_string_index++] = c;
|
||||
cxt->search_string[cxt->search_string_index++] = cxt->lastc; /* XXX - was c instead of lastc */
|
||||
cxt->search_string[cxt->search_string_index] = '\0';
|
||||
break;
|
||||
}
|
||||
|
@ -606,6 +697,7 @@ _rl_isearch_dispatch (cxt, c)
|
|||
/* We cannot find the search string. Ding the bell. */
|
||||
rl_ding ();
|
||||
cxt->history_pos = cxt->last_found_line;
|
||||
rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -618,7 +710,7 @@ _rl_isearch_dispatch (cxt, c)
|
|||
rl_replace_line (cxt->lines[cxt->history_pos], 0);
|
||||
rl_point = cxt->sline_index;
|
||||
cxt->last_found_line = cxt->history_pos;
|
||||
rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
|
||||
rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -653,7 +745,7 @@ rl_search_history (direction, invoking_key)
|
|||
RL_SETSTATE(RL_STATE_ISEARCH);
|
||||
cxt = _rl_isearch_init (direction);
|
||||
|
||||
rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1);
|
||||
rl_display_search (cxt->search_string, cxt->sflags, -1);
|
||||
|
||||
/* If we are using the callback interface, all we do is set up here and
|
||||
return. The key is that we leave RL_STATE_ISEARCH set. */
|
||||
|
|
|
@ -121,6 +121,19 @@ _rl_next_macro_key ()
|
|||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
_rl_prev_macro_key ()
|
||||
{
|
||||
if (rl_executing_macro == 0)
|
||||
return (0);
|
||||
|
||||
if (executing_macro_index == 0)
|
||||
return (0);
|
||||
|
||||
executing_macro_index--;
|
||||
return (rl_executing_macro[executing_macro_index]);
|
||||
}
|
||||
|
||||
/* Save the currently executing macro on a stack of saved macros. */
|
||||
void
|
||||
_rl_push_executing_macro ()
|
||||
|
@ -234,7 +247,7 @@ rl_end_kbd_macro (count, ignore)
|
|||
return -1;
|
||||
}
|
||||
|
||||
current_macro_index -= rl_key_sequence_length - 1;
|
||||
current_macro_index -= rl_key_sequence_length;
|
||||
current_macro[current_macro_index] = '\0';
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_MACRODEF);
|
||||
|
@ -263,6 +276,29 @@ rl_call_last_kbd_macro (count, ignore)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rl_print_last_kbd_macro (count, ignore)
|
||||
int count, ignore;
|
||||
{
|
||||
char *m;
|
||||
|
||||
if (current_macro == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
return 0;
|
||||
}
|
||||
m = _rl_untranslate_macro_value (current_macro, 1);
|
||||
rl_crlf ();
|
||||
printf ("%s", m);
|
||||
fflush (stdout);
|
||||
rl_crlf ();
|
||||
FREE (m);
|
||||
rl_forced_update_display ();
|
||||
rl_display_fixed = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rl_push_macro_input (macro)
|
||||
char *macro;
|
||||
|
|
|
@ -64,6 +64,9 @@ int rl_byte_oriented = 0;
|
|||
int rl_byte_oriented = 1;
|
||||
#endif
|
||||
|
||||
/* Ditto */
|
||||
int _rl_utf8locale = 0;
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Multibyte Character Utility Functions */
|
||||
|
@ -119,7 +122,7 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
|
|||
point += tmp;
|
||||
if (find_non_zero)
|
||||
{
|
||||
if (wcwidth (wc) == 0)
|
||||
if (WCWIDTH (wc) == 0)
|
||||
continue;
|
||||
else
|
||||
count--;
|
||||
|
@ -132,7 +135,7 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
|
|||
if (find_non_zero)
|
||||
{
|
||||
tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
|
||||
while (MB_NULLWCH (tmp) == 0 && MB_INVALIDCH (tmp) == 0 && wcwidth (wc) == 0)
|
||||
while (MB_NULLWCH (tmp) == 0 && MB_INVALIDCH (tmp) == 0 && WCWIDTH (wc) == 0)
|
||||
{
|
||||
point += tmp;
|
||||
tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
|
||||
|
@ -184,7 +187,7 @@ _rl_find_prev_mbchar_internal (string, seed, find_non_zero)
|
|||
{
|
||||
if (find_non_zero)
|
||||
{
|
||||
if (wcwidth (wc) != 0)
|
||||
if (WCWIDTH (wc) != 0)
|
||||
prev = point;
|
||||
}
|
||||
else
|
||||
|
@ -263,7 +266,7 @@ _rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2)
|
|||
if point is invalied (point < 0 || more than string length),
|
||||
it returns -1 */
|
||||
int
|
||||
_rl_adjust_point(string, point, ps)
|
||||
_rl_adjust_point (string, point, ps)
|
||||
char *string;
|
||||
int point;
|
||||
mbstate_t *ps;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* misc.c -- miscellaneous bindable readline functions. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2012 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,8 @@
|
|||
static int rl_digit_loop PARAMS((void));
|
||||
static void _rl_history_set_point PARAMS((void));
|
||||
|
||||
extern int history_offset;
|
||||
|
||||
/* Forward declarations used in this file */
|
||||
void _rl_free_history_entry PARAMS((HIST_ENTRY *));
|
||||
|
||||
|
@ -483,6 +485,37 @@ _rl_revert_all_lines ()
|
|||
xfree (lbuf);
|
||||
}
|
||||
|
||||
/* Free the history list, including private readline data and take care
|
||||
of pointer aliases to history data. Resets rl_undo_list if it points
|
||||
to an UNDO_LIST * saved as some history entry's data member. This
|
||||
should not be called while editing is active. */
|
||||
void
|
||||
rl_clear_history ()
|
||||
{
|
||||
HIST_ENTRY **hlist, *hent;
|
||||
register int i;
|
||||
UNDO_LIST *ul, *saved_undo_list;
|
||||
|
||||
saved_undo_list = rl_undo_list;
|
||||
hlist = history_list (); /* direct pointer, not copy */
|
||||
|
||||
for (i = 0; i < history_length; i++)
|
||||
{
|
||||
hent = hlist[i];
|
||||
if (ul = (UNDO_LIST *)hent->data)
|
||||
{
|
||||
if (ul == saved_undo_list)
|
||||
saved_undo_list = 0;
|
||||
_rl_free_undo_list (ul);
|
||||
hent->data = 0;
|
||||
}
|
||||
_rl_free_history_entry (hent);
|
||||
}
|
||||
|
||||
history_offset = history_length = 0;
|
||||
rl_undo_list = saved_undo_list; /* should be NULL */
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* History Commands */
|
||||
|
@ -623,6 +656,10 @@ rl_emacs_editing_mode (count, key)
|
|||
rl_editing_mode = emacs_mode;
|
||||
_rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
|
||||
_rl_keymap = emacs_standard_keymap;
|
||||
|
||||
if (_rl_show_mode_in_prompt)
|
||||
_rl_reset_prompt ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,10 @@
|
|||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LANGINFO_CODESET)
|
||||
# include <langinfo.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "rldefs.h"
|
||||
|
@ -50,6 +54,8 @@
|
|||
#include "rlshell.h"
|
||||
#include "rlprivate.h"
|
||||
|
||||
static int utf8locale PARAMS((char *));
|
||||
|
||||
#if !defined (HAVE_SETLOCALE)
|
||||
/* A list of legal values for the LANG or LC_CTYPE environment variables.
|
||||
If a locale name in this list is the value for the LC_ALL, LC_CTYPE,
|
||||
|
@ -72,9 +78,10 @@ static char *legal_lang_values[] =
|
|||
};
|
||||
|
||||
static char *normalize_codeset PARAMS((char *));
|
||||
static char *find_codeset PARAMS((char *, size_t *));
|
||||
#endif /* !HAVE_SETLOCALE */
|
||||
|
||||
static char *find_codeset PARAMS((char *, size_t *));
|
||||
|
||||
static char *_rl_get_locale_var PARAMS((const char *));
|
||||
|
||||
static char *
|
||||
|
@ -91,7 +98,26 @@ _rl_get_locale_var (v)
|
|||
|
||||
return lspec;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
utf8locale (lspec)
|
||||
char *lspec;
|
||||
{
|
||||
char *cp;
|
||||
size_t len;
|
||||
|
||||
#if HAVE_LANGINFO_CODESET
|
||||
cp = nl_langinfo (CODESET);
|
||||
return (STREQ (cp, "UTF-8") || STREQ (cp, "utf8"));
|
||||
#else
|
||||
cp = find_codeset (lspec, &len);
|
||||
|
||||
if (cp == 0 || len < 4 || len > 5)
|
||||
return 0;
|
||||
return ((len == 5) ? strncmp (cp, "UTF-8", len) == 0 : strncmp (cp, "utf8", 4) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value
|
||||
to decide the defaults for 8-bit character input and output. Returns
|
||||
1 if we set eight-bit mode. */
|
||||
|
@ -116,6 +142,9 @@ _rl_init_eightbit ()
|
|||
lspec = "";
|
||||
t = setlocale (LC_CTYPE, lspec);
|
||||
|
||||
if (t && *t)
|
||||
_rl_utf8locale = utf8locale (t);
|
||||
|
||||
if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
|
||||
{
|
||||
_rl_meta_flag = 1;
|
||||
|
@ -197,6 +226,7 @@ normalize_codeset (codeset)
|
|||
|
||||
return retval;
|
||||
}
|
||||
#endif /* !HAVE_SETLOCALE */
|
||||
|
||||
/* Isolate codeset portion of locale specification. */
|
||||
static char *
|
||||
|
@ -249,4 +279,3 @@ find_codeset (name, lenp)
|
|||
|
||||
return result;
|
||||
}
|
||||
#endif /* !HAVE_SETLOCALE */
|
||||
|
|
440
lib/readline/parse-colors.c
Normal file
440
lib/readline/parse-colors.c
Normal file
|
@ -0,0 +1,440 @@
|
|||
/* `dir', `vdir' and `ls' directory listing programs for GNU.
|
||||
|
||||
Modified by Chet Ramey for Readline.
|
||||
|
||||
Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 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/>. */
|
||||
|
||||
/* Written by Richard Stallman and David MacKenzie. */
|
||||
|
||||
/* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis
|
||||
Flaherty <dennisf@denix.elk.miles.com> based on original patches by
|
||||
Greg Lee <lee@uhunix.uhcc.hawaii.edu>. */
|
||||
|
||||
#define READLINE_LIBRARY
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// strdup() / strcpy()
|
||||
#if defined (HAVE_STRING_H)
|
||||
# include <string.h>
|
||||
#else /* !HAVE_STRING_H */
|
||||
# include <strings.h>
|
||||
#endif /* !HAVE_STRING_H */
|
||||
|
||||
// abort()
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#include "rldefs.h" // STREQ, savestring
|
||||
#include "readline.h"
|
||||
#include "rlprivate.h"
|
||||
#include "rlshell.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#include "colors.h"
|
||||
#include "parse-colors.h"
|
||||
|
||||
#if defined (COLOR_SUPPORT)
|
||||
|
||||
static bool get_funky_string (char **dest, const char **src, bool equals_end, size_t *output_count);
|
||||
|
||||
struct bin_str _rl_color_indicator[] =
|
||||
{
|
||||
{ LEN_STR_PAIR ("\033[") }, // lc: Left of color sequence
|
||||
{ LEN_STR_PAIR ("m") }, // rc: Right of color sequence
|
||||
{ 0, NULL }, // ec: End color (replaces lc+no+rc)
|
||||
{ LEN_STR_PAIR ("0") }, // rs: Reset to ordinary colors
|
||||
{ 0, NULL }, // no: Normal
|
||||
{ 0, NULL }, // fi: File: default
|
||||
{ LEN_STR_PAIR ("01;34") }, // di: Directory: bright blue
|
||||
{ LEN_STR_PAIR ("01;36") }, // ln: Symlink: bright cyan
|
||||
{ LEN_STR_PAIR ("33") }, // pi: Pipe: yellow/brown
|
||||
{ LEN_STR_PAIR ("01;35") }, // so: Socket: bright magenta
|
||||
{ LEN_STR_PAIR ("01;33") }, // bd: Block device: bright yellow
|
||||
{ LEN_STR_PAIR ("01;33") }, // cd: Char device: bright yellow
|
||||
{ 0, NULL }, // mi: Missing file: undefined
|
||||
{ 0, NULL }, // or: Orphaned symlink: undefined
|
||||
{ LEN_STR_PAIR ("01;32") }, // ex: Executable: bright green
|
||||
{ LEN_STR_PAIR ("01;35") }, // do: Door: bright magenta
|
||||
{ LEN_STR_PAIR ("37;41") }, // su: setuid: white on red
|
||||
{ LEN_STR_PAIR ("30;43") }, // sg: setgid: black on yellow
|
||||
{ LEN_STR_PAIR ("37;44") }, // st: sticky: black on blue
|
||||
{ LEN_STR_PAIR ("34;42") }, // ow: other-writable: blue on green
|
||||
{ LEN_STR_PAIR ("30;42") }, // tw: ow w/ sticky: black on green
|
||||
{ LEN_STR_PAIR ("30;41") }, // ca: black on red
|
||||
{ 0, NULL }, // mh: disabled by default
|
||||
{ LEN_STR_PAIR ("\033[K") }, // cl: clear to end of line
|
||||
};
|
||||
|
||||
/* Parse a string as part of the LS_COLORS variable; this may involve
|
||||
decoding all kinds of escape characters. If equals_end is set an
|
||||
unescaped equal sign ends the string, otherwise only a : or \0
|
||||
does. Set *OUTPUT_COUNT to the number of bytes output. Return
|
||||
true if successful.
|
||||
|
||||
The resulting string is *not* null-terminated, but may contain
|
||||
embedded nulls.
|
||||
|
||||
Note that both dest and src are char **; on return they point to
|
||||
the first free byte after the array and the character that ended
|
||||
the input string, respectively. */
|
||||
|
||||
static bool
|
||||
get_funky_string (char **dest, const char **src, bool equals_end, size_t *output_count) {
|
||||
char num; /* For numerical codes */
|
||||
size_t count; /* Something to count with */
|
||||
enum {
|
||||
ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR
|
||||
} state;
|
||||
const char *p;
|
||||
char *q;
|
||||
|
||||
p = *src; /* We don't want to double-indirect */
|
||||
q = *dest; /* the whole darn time. */
|
||||
|
||||
count = 0; /* No characters counted in yet. */
|
||||
num = 0;
|
||||
|
||||
state = ST_GND; /* Start in ground state. */
|
||||
while (state < ST_END)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case ST_GND: /* Ground state (no escapes) */
|
||||
switch (*p)
|
||||
{
|
||||
case ':':
|
||||
case '\0':
|
||||
state = ST_END; /* End of string */
|
||||
break;
|
||||
case '\\':
|
||||
state = ST_BACKSLASH; /* Backslash scape sequence */
|
||||
++p;
|
||||
break;
|
||||
case '^':
|
||||
state = ST_CARET; /* Caret escape */
|
||||
++p;
|
||||
break;
|
||||
case '=':
|
||||
if (equals_end)
|
||||
{
|
||||
state = ST_END; /* End */
|
||||
break;
|
||||
}
|
||||
/* else fall through */
|
||||
default:
|
||||
*(q++) = *(p++);
|
||||
++count;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_BACKSLASH: /* Backslash escaped character */
|
||||
switch (*p)
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
state = ST_OCTAL; /* Octal sequence */
|
||||
num = *p - '0';
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
state = ST_HEX; /* Hex sequence */
|
||||
num = 0;
|
||||
break;
|
||||
case 'a': /* Bell */
|
||||
num = '\a';
|
||||
break;
|
||||
case 'b': /* Backspace */
|
||||
num = '\b';
|
||||
break;
|
||||
case 'e': /* Escape */
|
||||
num = 27;
|
||||
break;
|
||||
case 'f': /* Form feed */
|
||||
num = '\f';
|
||||
break;
|
||||
case 'n': /* Newline */
|
||||
num = '\n';
|
||||
break;
|
||||
case 'r': /* Carriage return */
|
||||
num = '\r';
|
||||
break;
|
||||
case 't': /* Tab */
|
||||
num = '\t';
|
||||
break;
|
||||
case 'v': /* Vtab */
|
||||
num = '\v';
|
||||
break;
|
||||
case '?': /* Delete */
|
||||
num = 127;
|
||||
break;
|
||||
case '_': /* Space */
|
||||
num = ' ';
|
||||
break;
|
||||
case '\0': /* End of string */
|
||||
state = ST_ERROR; /* Error! */
|
||||
break;
|
||||
default: /* Escaped character like \ ^ : = */
|
||||
num = *p;
|
||||
break;
|
||||
}
|
||||
if (state == ST_BACKSLASH)
|
||||
{
|
||||
*(q++) = num;
|
||||
++count;
|
||||
state = ST_GND;
|
||||
}
|
||||
++p;
|
||||
break;
|
||||
|
||||
case ST_OCTAL: /* Octal sequence */
|
||||
if (*p < '0' || *p > '7')
|
||||
{
|
||||
*(q++) = num;
|
||||
++count;
|
||||
state = ST_GND;
|
||||
}
|
||||
else
|
||||
num = (num << 3) + (*(p++) - '0');
|
||||
break;
|
||||
|
||||
case ST_HEX: /* Hex sequence */
|
||||
switch (*p)
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
num = (num << 4) + (*(p++) - '0');
|
||||
break;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
num = (num << 4) + (*(p++) - 'a') + 10;
|
||||
break;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
num = (num << 4) + (*(p++) - 'A') + 10;
|
||||
break;
|
||||
default:
|
||||
*(q++) = num;
|
||||
++count;
|
||||
state = ST_GND;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_CARET: /* Caret escape */
|
||||
state = ST_GND; /* Should be the next state... */
|
||||
if (*p >= '@' && *p <= '~')
|
||||
{
|
||||
*(q++) = *(p++) & 037;
|
||||
++count;
|
||||
}
|
||||
else if (*p == '?')
|
||||
{
|
||||
*(q++) = 127;
|
||||
++count;
|
||||
}
|
||||
else
|
||||
state = ST_ERROR;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* should we ? */
|
||||
/* abort (); no, we should not */
|
||||
state = ST_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*dest = q;
|
||||
*src = p;
|
||||
*output_count = count;
|
||||
|
||||
return state != ST_ERROR;
|
||||
}
|
||||
#endif /* COLOR_SUPPORT */
|
||||
|
||||
void _rl_parse_colors()
|
||||
{
|
||||
#if defined (COLOR_SUPPORT)
|
||||
const char *p; /* Pointer to character being parsed */
|
||||
char *buf; /* color_buf buffer pointer */
|
||||
int state; /* State of parser */
|
||||
int ind_no; /* Indicator number */
|
||||
char label[3]; /* Indicator label */
|
||||
COLOR_EXT_TYPE *ext; /* Extension we are working on */
|
||||
|
||||
p = sh_get_env_value ("LS_COLORS");
|
||||
if (p == 0 || *p == '\0')
|
||||
{
|
||||
_rl_color_ext_list = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
ext = NULL;
|
||||
strcpy (label, "??");
|
||||
|
||||
/* This is an overly conservative estimate, but any possible
|
||||
LS_COLORS string will *not* generate a color_buf longer than
|
||||
itself, so it is a safe way of allocating a buffer in
|
||||
advance. */
|
||||
buf = color_buf = savestring (p);
|
||||
|
||||
state = 1;
|
||||
while (state > 0)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case 1: /* First label character */
|
||||
switch (*p)
|
||||
{
|
||||
case ':':
|
||||
++p;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
/* Allocate new extension block and add to head of
|
||||
linked list (this way a later definition will
|
||||
override an earlier one, which can be useful for
|
||||
having terminal-specific defs override global). */
|
||||
|
||||
ext = (COLOR_EXT_TYPE *)xmalloc (sizeof *ext);
|
||||
ext->next = _rl_color_ext_list;
|
||||
_rl_color_ext_list = ext;
|
||||
|
||||
++p;
|
||||
ext->ext.string = buf;
|
||||
|
||||
state = (get_funky_string (&buf, &p, true, &ext->ext.len)
|
||||
? 4 : -1);
|
||||
break;
|
||||
|
||||
case '\0':
|
||||
state = 0; /* Done! */
|
||||
break;
|
||||
|
||||
default: /* Assume it is file type label */
|
||||
label[0] = *(p++);
|
||||
state = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* Second label character */
|
||||
if (*p)
|
||||
{
|
||||
label[1] = *(p++);
|
||||
state = 3;
|
||||
}
|
||||
else
|
||||
state = -1; /* Error */
|
||||
break;
|
||||
|
||||
case 3: /* Equal sign after indicator label */
|
||||
state = -1; /* Assume failure... */
|
||||
if (*(p++) == '=')/* It *should* be... */
|
||||
{
|
||||
for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no)
|
||||
{
|
||||
if (STREQ (label, indicator_name[ind_no]))
|
||||
{
|
||||
_rl_color_indicator[ind_no].string = buf;
|
||||
state = (get_funky_string (&buf, &p, false,
|
||||
&_rl_color_indicator[ind_no].len)
|
||||
? 1 : -1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (state == -1)
|
||||
{
|
||||
_rl_errmsg ("LS_COLORS: unrecognized prefix: %s", label);
|
||||
/* recover from an unrecognized prefix */
|
||||
while (p && *p && *p != ':')
|
||||
p++;
|
||||
if (p && *p == ':')
|
||||
state = 1;
|
||||
else if (p && *p == 0)
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: /* Equal sign after *.ext */
|
||||
if (*(p++) == '=')
|
||||
{
|
||||
ext->seq.string = buf;
|
||||
state = (get_funky_string (&buf, &p, false, &ext->seq.len)
|
||||
? 1 : -1);
|
||||
}
|
||||
else
|
||||
state = -1;
|
||||
/* XXX - recover here as with an unrecognized prefix? */
|
||||
if (state == -1 && ext->ext.string)
|
||||
_rl_errmsg ("LS_COLORS: syntax error: %s", ext->ext.string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state < 0)
|
||||
{
|
||||
COLOR_EXT_TYPE *e;
|
||||
COLOR_EXT_TYPE *e2;
|
||||
|
||||
_rl_errmsg ("unparsable value for LS_COLORS environment variable");
|
||||
free (color_buf);
|
||||
for (e = _rl_color_ext_list; e != NULL; /* empty */)
|
||||
{
|
||||
e2 = e;
|
||||
e = e->next;
|
||||
free (e2);
|
||||
}
|
||||
_rl_color_ext_list = NULL;
|
||||
_rl_colored_stats = 0; /* can't have colored stats without colors */
|
||||
}
|
||||
#else /* !COLOR_SUPPORT */
|
||||
;
|
||||
#endif /* !COLOR_SUPPORT */
|
||||
}
|
46
lib/readline/parse-colors.h
Normal file
46
lib/readline/parse-colors.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* `dir', `vdir' and `ls' directory listing programs for GNU.
|
||||
|
||||
Modified by Chet Ramey for Readline.
|
||||
|
||||
Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 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/>. */
|
||||
|
||||
/* Written by Richard Stallman and David MacKenzie. */
|
||||
|
||||
/* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis
|
||||
Flaherty <dennisf@denix.elk.miles.com> based on original patches by
|
||||
Greg Lee <lee@uhunix.uhcc.hawaii.edu>. */
|
||||
|
||||
#ifndef _PARSE_COLORS_H_
|
||||
#define _PARSE_COLORS_H_
|
||||
|
||||
#include "readline.h"
|
||||
|
||||
#define LEN_STR_PAIR(s) sizeof (s) - 1, s
|
||||
|
||||
void _rl_parse_colors (void);
|
||||
|
||||
static const char *const indicator_name[]=
|
||||
{
|
||||
"lc", "rc", "ec", "rs", "no", "fi", "di", "ln", "pi", "so",
|
||||
"bd", "cd", "mi", "or", "ex", "do", "su", "sg", "st",
|
||||
"ow", "tw", "ca", "mh", "cl", NULL
|
||||
};
|
||||
|
||||
/* Buffer for color sequences */
|
||||
static char *color_buf;
|
||||
|
||||
#endif /* !_PARSE_COLORS_H_ */
|
|
@ -1,6 +1,6 @@
|
|||
/* posixdir.h -- Posix directory reading includes and defines. */
|
||||
|
||||
/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987,1991,2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -46,16 +46,26 @@
|
|||
# define D_NAMLEN(d) ((d)->d_namlen)
|
||||
#endif /* !HAVE_DIRENT_H */
|
||||
|
||||
/* The bash code fairly consistenly uses d_fileno; make sure it's available */
|
||||
#if defined (HAVE_STRUCT_DIRENT_D_INO) && !defined (HAVE_STRUCT_DIRENT_D_FILENO)
|
||||
# define d_fileno d_ino
|
||||
#endif
|
||||
|
||||
#if defined (_POSIX_SOURCE) && (!defined (HAVE_STRUCT_DIRENT_D_INO) || defined (BROKEN_DIRENT_D_INO))
|
||||
/* Posix does not require that the d_ino field be present, and some
|
||||
systems do not provide it. */
|
||||
#if !defined (HAVE_STRUCT_DIRENT_D_INO) || defined (BROKEN_DIRENT_D_INO)
|
||||
# define REAL_DIR_ENTRY(dp) 1
|
||||
#else
|
||||
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
|
||||
#endif /* _POSIX_SOURCE */
|
||||
|
||||
#if defined (HAVE_STRUCT_DIRENT_D_INO) && !defined (BROKEN_DIRENT_D_INO)
|
||||
# define D_INO_AVAILABLE
|
||||
#endif
|
||||
|
||||
/* Signal the rest of the code that it can safely use dirent.d_fileno */
|
||||
#if defined (D_INO_AVAILABLE) || defined (HAVE_STRUCT_DIRENT_D_FILENO)
|
||||
# define D_FILENO_AVAILABLE 1
|
||||
#endif
|
||||
|
||||
#endif /* !_POSIXDIR_H_ */
|
||||
|
|
|
@ -30,11 +30,13 @@
|
|||
# if !defined (__OPENNT)
|
||||
# undef setjmp
|
||||
# define setjmp(x) sigsetjmp((x), 1)
|
||||
# define setjmp_nosigs(x) sigsetjmp((x), 0)
|
||||
# undef longjmp
|
||||
# define longjmp(x, n) siglongjmp((x), (n))
|
||||
# endif /* !__OPENNT */
|
||||
#else
|
||||
# define procenv_t jmp_buf
|
||||
# define setjmp_nosigs setjmp
|
||||
#endif
|
||||
|
||||
#endif /* _POSIXJMP_H_ */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* readline.c -- a general facility for reading lines of input
|
||||
with emacs style editing and completion. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2013 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.
|
||||
|
@ -82,6 +82,11 @@ extern int errno;
|
|||
|
||||
extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
|
||||
|
||||
#if defined (COLOR_SUPPORT)
|
||||
extern void _rl_parse_colors PARAMS((void)); /* XXX */
|
||||
#endif
|
||||
|
||||
|
||||
/* Forward declarations used in this file. */
|
||||
static char *readline_internal PARAMS((void));
|
||||
static void readline_initialize_everything PARAMS((void));
|
||||
|
@ -112,7 +117,6 @@ int rl_gnu_readline_p = 1;
|
|||
By default, it is the standard emacs keymap. */
|
||||
Keymap _rl_keymap = emacs_standard_keymap;
|
||||
|
||||
|
||||
/* The current style of editing. */
|
||||
int rl_editing_mode = emacs_mode;
|
||||
|
||||
|
@ -238,13 +242,32 @@ int rl_erase_empty_line = 0;
|
|||
character bound to accept-line. */
|
||||
int rl_num_chars_to_read;
|
||||
|
||||
/* Line buffer and maintenence. */
|
||||
/* Line buffer and maintenance. */
|
||||
char *rl_line_buffer = (char *)NULL;
|
||||
int rl_line_buffer_len = 0;
|
||||
|
||||
/* Key sequence `contexts' */
|
||||
_rl_keyseq_cxt *_rl_kscxt = 0;
|
||||
|
||||
int rl_executing_key;
|
||||
char *rl_executing_keyseq = 0;
|
||||
int _rl_executing_keyseq_size = 0;
|
||||
|
||||
/* Timeout (specified in milliseconds) when reading characters making up an
|
||||
ambiguous multiple-key sequence */
|
||||
int _rl_keyseq_timeout = 500;
|
||||
|
||||
#define RESIZE_KEYSEQ_BUFFER() \
|
||||
do \
|
||||
{ \
|
||||
if (rl_key_sequence_length + 2 >= _rl_executing_keyseq_size) \
|
||||
{ \
|
||||
_rl_executing_keyseq_size += 16; \
|
||||
rl_executing_keyseq = xrealloc (rl_executing_keyseq, _rl_executing_keyseq_size); \
|
||||
} \
|
||||
} \
|
||||
while (0);
|
||||
|
||||
/* Forward declarations used by the display, termcap, and history code. */
|
||||
|
||||
/* **************************************************************** */
|
||||
|
@ -279,6 +302,10 @@ int _rl_revert_all_at_newline = 0;
|
|||
characters corresponding to keyboard-generated signals. */
|
||||
int _rl_echo_control_chars = 1;
|
||||
|
||||
/* Non-zero means to prefix the displayed prompt with a character indicating
|
||||
the editing mode: @ for emacs, : for vi-command, + for vi-insert. */
|
||||
int _rl_show_mode_in_prompt = 0;
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Top Level Functions */
|
||||
|
@ -352,6 +379,11 @@ readline (prompt)
|
|||
RL_SETSTATE (RL_STATE_CALLBACK);
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_AUDIT_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT)
|
||||
if (value)
|
||||
_rl_audit_tty (value);
|
||||
#endif
|
||||
|
||||
return (value);
|
||||
}
|
||||
|
||||
|
@ -369,9 +401,19 @@ readline_internal_setup ()
|
|||
_rl_in_stream = rl_instream;
|
||||
_rl_out_stream = rl_outstream;
|
||||
|
||||
/* Enable the meta key only for the duration of readline(), if this
|
||||
terminal has one and the terminal has been initialized */
|
||||
if (_rl_enable_meta & RL_ISSTATE (RL_STATE_TERMPREPPED))
|
||||
_rl_enable_meta_key ();
|
||||
|
||||
if (rl_startup_hook)
|
||||
(*rl_startup_hook) ();
|
||||
|
||||
#if defined (VI_MODE)
|
||||
if (rl_editing_mode == vi_mode)
|
||||
rl_vi_insertion_mode (1, 'i'); /* don't want to reset last */
|
||||
#endif /* VI_MODE */
|
||||
|
||||
/* If we're not echoing, we still want to at least print a prompt, because
|
||||
rl_redisplay will not do it for us. If the calling application has a
|
||||
custom redisplay function, though, let that function handle it. */
|
||||
|
@ -394,11 +436,6 @@ readline_internal_setup ()
|
|||
(*rl_redisplay_function) ();
|
||||
}
|
||||
|
||||
#if defined (VI_MODE)
|
||||
if (rl_editing_mode == vi_mode)
|
||||
rl_vi_insert_mode (1, 'i');
|
||||
#endif /* VI_MODE */
|
||||
|
||||
if (rl_pre_input_hook)
|
||||
(*rl_pre_input_hook) ();
|
||||
|
||||
|
@ -437,6 +474,11 @@ readline_internal_teardown (eof)
|
|||
if (rl_undo_list)
|
||||
rl_free_undo_list ();
|
||||
|
||||
/* Disable the meta key, if this terminal has one and we were told to use it.
|
||||
The check whether or not we sent the enable string is in
|
||||
_rl_disable_meta_key(); the flag is set in _rl_enable_meta_key */
|
||||
_rl_disable_meta_key ();
|
||||
|
||||
/* Restore normal cursor, if available. */
|
||||
_rl_set_insert_mode (RL_IM_INSERT, 0);
|
||||
|
||||
|
@ -492,7 +534,11 @@ readline_internal_charloop ()
|
|||
#endif
|
||||
lk = _rl_last_command_was_kill;
|
||||
|
||||
#if defined (HAVE_POSIX_SIGSETJMP)
|
||||
code = sigsetjmp (_rl_top_level, 0);
|
||||
#else
|
||||
code = setjmp (_rl_top_level);
|
||||
#endif
|
||||
|
||||
if (code)
|
||||
{
|
||||
|
@ -511,6 +557,7 @@ readline_internal_charloop ()
|
|||
/* Then initialize the argument and number of keys read. */
|
||||
_rl_reset_argument ();
|
||||
rl_key_sequence_length = 0;
|
||||
rl_executing_keyseq[0] = 0;
|
||||
}
|
||||
|
||||
RL_SETSTATE(RL_STATE_READCMD);
|
||||
|
@ -519,7 +566,8 @@ readline_internal_charloop ()
|
|||
|
||||
/* look at input.c:rl_getc() for the circumstances under which this will
|
||||
be returned; punt immediately on read error without converting it to
|
||||
a newline. */
|
||||
a newline; assume that rl_read_key has already called the signal
|
||||
handler. */
|
||||
if (c == READERR)
|
||||
{
|
||||
#if defined (READLINE_CALLBACKS)
|
||||
|
@ -531,7 +579,9 @@ readline_internal_charloop ()
|
|||
#endif
|
||||
}
|
||||
|
||||
/* EOF typed to a non-blank line is a <NL>. */
|
||||
/* EOF typed to a non-blank line is a <NL>. If we want to change this,
|
||||
to force any existing line to be ignored when read(2) reads EOF,
|
||||
for example, this is the place to change. */
|
||||
if (c == EOF && rl_end)
|
||||
c = NEWLINE;
|
||||
|
||||
|
@ -743,9 +793,10 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
|||
{
|
||||
if (RL_ISSTATE (RL_STATE_MACRODEF))
|
||||
_rl_add_macro_char (ESC);
|
||||
RESIZE_KEYSEQ_BUFFER ();
|
||||
rl_executing_keyseq[rl_key_sequence_length++] = ESC;
|
||||
map = FUNCTION_TO_KEYMAP (map, ESC);
|
||||
key = UNMETA (key);
|
||||
rl_key_sequence_length += 2;
|
||||
return (_rl_dispatch (key, map));
|
||||
}
|
||||
else
|
||||
|
@ -765,13 +816,19 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
|||
{
|
||||
/* Special case rl_do_lowercase_version (). */
|
||||
if (func == rl_do_lowercase_version)
|
||||
/* Should we do anything special if key == ANYOTHERKEY? */
|
||||
return (_rl_dispatch (_rl_to_lower (key), map));
|
||||
|
||||
rl_executing_keymap = map;
|
||||
rl_executing_key = key;
|
||||
|
||||
RESIZE_KEYSEQ_BUFFER();
|
||||
rl_executing_keyseq[rl_key_sequence_length++] = key;
|
||||
rl_executing_keyseq[rl_key_sequence_length] = '\0';
|
||||
|
||||
rl_dispatching = 1;
|
||||
RL_SETSTATE(RL_STATE_DISPATCHING);
|
||||
(*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
|
||||
r = (*func) (rl_numeric_arg * rl_arg_sign, key);
|
||||
RL_UNSETSTATE(RL_STATE_DISPATCHING);
|
||||
rl_dispatching = 0;
|
||||
|
||||
|
@ -788,7 +845,10 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
|||
/* OK, there's no function bound in this map, but there is a
|
||||
shadow function that was overridden when the current keymap
|
||||
was created. Return -2 to note that. */
|
||||
_rl_unget_char (key);
|
||||
if (RL_ISSTATE (RL_STATE_MACROINPUT))
|
||||
_rl_prev_macro_key ();
|
||||
else
|
||||
_rl_unget_char (key);
|
||||
return -2;
|
||||
}
|
||||
else if (got_subseq)
|
||||
|
@ -797,7 +857,10 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
|||
have a matching key, nor was one overridden. This means
|
||||
we need to back up the recursion chain and find the last
|
||||
subsequence that is bound to a function. */
|
||||
_rl_unget_char (key);
|
||||
if (RL_ISSTATE (RL_STATE_MACROINPUT))
|
||||
_rl_prev_macro_key ();
|
||||
else
|
||||
_rl_unget_char (key);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
|
@ -820,13 +883,17 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
|||
check whether there's input in the queue, which there generally
|
||||
will be if an arrow key has been pressed, and, if there's not,
|
||||
just dispatch to (what we assume is) rl_vi_movement_mode right
|
||||
away. This is essentially an input test with a zero timeout. */
|
||||
away. This is essentially an input test with a zero timeout (by
|
||||
default) or a timeout determined by the value of `keyseq-timeout' */
|
||||
/* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
|
||||
takes microseconds, so multiply by 1000 */
|
||||
if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap
|
||||
&& _rl_input_queued (0) == 0)
|
||||
&& _rl_input_queued ((_rl_keyseq_timeout > 0) ? _rl_keyseq_timeout*1000 : 0) == 0)
|
||||
return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
|
||||
#endif
|
||||
|
||||
rl_key_sequence_length++;
|
||||
RESIZE_KEYSEQ_BUFFER ();
|
||||
rl_executing_keyseq[rl_key_sequence_length++] = key;
|
||||
_rl_dispatching_keymap = FUNCTION_TO_KEYMAP (map, key);
|
||||
|
||||
/* Allocate new context here. Use linked contexts (linked through
|
||||
|
@ -855,6 +922,18 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Tentative inter-character timeout for potential multi-key
|
||||
sequences? If no input within timeout, abort sequence and
|
||||
act as if we got non-matching input. */
|
||||
/* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
|
||||
takes microseconds, so multiply by 1000 */
|
||||
if (_rl_keyseq_timeout > 0 &&
|
||||
(RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) &&
|
||||
_rl_pushed_input_available () == 0 &&
|
||||
_rl_dispatching_keymap[ANYOTHERKEY].function &&
|
||||
_rl_input_queued (_rl_keyseq_timeout*1000) == 0)
|
||||
return (_rl_subseq_result (-2, map, key, got_subseq));
|
||||
|
||||
newkey = _rl_subseq_getchar (key);
|
||||
if (newkey < 0)
|
||||
{
|
||||
|
@ -875,6 +954,7 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
|||
case ISMACR:
|
||||
if (map[key].function != 0)
|
||||
{
|
||||
rl_executing_keyseq[rl_key_sequence_length] = '\0';
|
||||
macro = savestring ((char *)map[key].function);
|
||||
_rl_with_macro_input (macro);
|
||||
return 0;
|
||||
|
@ -884,6 +964,7 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
|||
#if defined (VI_MODE)
|
||||
if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap &&
|
||||
key != ANYOTHERKEY &&
|
||||
rl_key_sequence_length == 1 && /* XXX */
|
||||
_rl_vi_textmod_command (key))
|
||||
_rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
|
||||
#endif
|
||||
|
@ -935,14 +1016,20 @@ _rl_subseq_result (r, map, key, got_subseq)
|
|||
/* We didn't match (r is probably -1), so return something to
|
||||
tell the caller that it should try ANYOTHERKEY for an
|
||||
overridden function. */
|
||||
_rl_unget_char (key);
|
||||
if (RL_ISSTATE (RL_STATE_MACROINPUT))
|
||||
_rl_prev_macro_key ();
|
||||
else
|
||||
_rl_unget_char (key);
|
||||
_rl_dispatching_keymap = map;
|
||||
return -2;
|
||||
}
|
||||
else if (r && got_subseq)
|
||||
{
|
||||
/* OK, back up the chain. */
|
||||
_rl_unget_char (key);
|
||||
if (RL_ISSTATE (RL_STATE_MACROINPUT))
|
||||
_rl_prev_macro_key ();
|
||||
else
|
||||
_rl_unget_char (key);
|
||||
_rl_dispatching_keymap = map;
|
||||
return -1;
|
||||
}
|
||||
|
@ -971,7 +1058,7 @@ rl_initialize ()
|
|||
RL_SETSTATE(RL_STATE_INITIALIZED);
|
||||
}
|
||||
|
||||
/* Initalize the current line information. */
|
||||
/* Initialize the current line information. */
|
||||
_rl_init_line_state ();
|
||||
|
||||
/* We aren't done yet. We haven't even gotten started yet! */
|
||||
|
@ -1091,14 +1178,19 @@ readline_initialize_everything ()
|
|||
/* Try to bind a common arrow key prefix, if not already bound. */
|
||||
bind_arrow_keys ();
|
||||
|
||||
/* Enable the meta key, if this terminal has one. */
|
||||
if (_rl_enable_meta)
|
||||
_rl_enable_meta_key ();
|
||||
|
||||
/* If the completion parser's default word break characters haven't
|
||||
been set yet, then do so now. */
|
||||
if (rl_completer_word_break_characters == (char *)NULL)
|
||||
rl_completer_word_break_characters = (char *)rl_basic_word_break_characters;
|
||||
|
||||
#if defined (COLOR_SUPPORT)
|
||||
if (_rl_colored_stats)
|
||||
_rl_parse_colors ();
|
||||
#endif
|
||||
|
||||
rl_executing_keyseq = malloc (_rl_executing_keyseq_size = 16);
|
||||
if (rl_executing_keyseq)
|
||||
rl_executing_keyseq[0] = '\0';
|
||||
}
|
||||
|
||||
/* If this system allows us to look at the values of the regular
|
||||
|
@ -1159,6 +1251,20 @@ bind_arrow_keys_internal (map)
|
|||
rl_bind_keyseq_if_unbound ("\340P", rl_get_next_history);
|
||||
rl_bind_keyseq_if_unbound ("\340M", rl_forward_char);
|
||||
rl_bind_keyseq_if_unbound ("\340K", rl_backward_char);
|
||||
rl_bind_keyseq_if_unbound ("\340G", rl_beg_of_line);
|
||||
rl_bind_keyseq_if_unbound ("\340O", rl_end_of_line);
|
||||
rl_bind_keyseq_if_unbound ("\340S", rl_delete);
|
||||
rl_bind_keyseq_if_unbound ("\340R", rl_overwrite_mode);
|
||||
|
||||
/* These may or may not work because of the embedded NUL. */
|
||||
rl_bind_keyseq_if_unbound ("\\000H", rl_get_previous_history);
|
||||
rl_bind_keyseq_if_unbound ("\\000P", rl_get_next_history);
|
||||
rl_bind_keyseq_if_unbound ("\\000M", rl_forward_char);
|
||||
rl_bind_keyseq_if_unbound ("\\000K", rl_backward_char);
|
||||
rl_bind_keyseq_if_unbound ("\\000G", rl_beg_of_line);
|
||||
rl_bind_keyseq_if_unbound ("\\000O", rl_end_of_line);
|
||||
rl_bind_keyseq_if_unbound ("\\000S", rl_delete);
|
||||
rl_bind_keyseq_if_unbound ("\\000R", rl_overwrite_mode);
|
||||
#endif
|
||||
|
||||
_rl_keymap = xkeymap;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Readline.h -- the names of functions callable from within readline. */
|
||||
|
||||
/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2013 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 0x0602 /* Readline 6.2 */
|
||||
#define RL_READLINE_VERSION 0x0603 /* Readline 6.3 */
|
||||
#define RL_VERSION_MAJOR 6
|
||||
#define RL_VERSION_MINOR 2
|
||||
#define RL_VERSION_MINOR 3
|
||||
|
||||
/* Readline data structures. */
|
||||
|
||||
|
@ -185,6 +185,7 @@ extern int rl_forward_search_history PARAMS((int, int));
|
|||
extern int rl_start_kbd_macro PARAMS((int, int));
|
||||
extern int rl_end_kbd_macro PARAMS((int, int));
|
||||
extern int rl_call_last_kbd_macro PARAMS((int, int));
|
||||
extern int rl_print_last_kbd_macro PARAMS((int, int));
|
||||
|
||||
/* Bindable undo commands. */
|
||||
extern int rl_revert_line PARAMS((int, int));
|
||||
|
@ -204,6 +205,8 @@ extern int rl_tty_status PARAMS((int, int));
|
|||
/* Bindable commands for incremental and non-incremental history searching. */
|
||||
extern int rl_history_search_forward PARAMS((int, int));
|
||||
extern int rl_history_search_backward PARAMS((int, int));
|
||||
extern int rl_history_substr_search_forward PARAMS((int, int));
|
||||
extern int rl_history_substr_search_backward PARAMS((int, int));
|
||||
extern int rl_noninc_forward_search PARAMS((int, int));
|
||||
extern int rl_noninc_reverse_search PARAMS((int, int));
|
||||
extern int rl_noninc_forward_search_again PARAMS((int, int));
|
||||
|
@ -339,6 +342,7 @@ extern Keymap rl_make_bare_keymap PARAMS((void));
|
|||
extern Keymap rl_copy_keymap PARAMS((Keymap));
|
||||
extern Keymap rl_make_keymap PARAMS((void));
|
||||
extern void rl_discard_keymap PARAMS((Keymap));
|
||||
extern void rl_free_keymap PARAMS((Keymap));
|
||||
|
||||
extern Keymap rl_get_keymap_by_name PARAMS((const char *));
|
||||
extern char *rl_get_keymap_name PARAMS((Keymap));
|
||||
|
@ -436,6 +440,10 @@ extern void rl_echo_signal_char PARAMS((int));
|
|||
|
||||
extern int rl_set_paren_blink_timeout PARAMS((int));
|
||||
|
||||
/* History management functions. */
|
||||
|
||||
extern void rl_clear_history PARAMS((void));
|
||||
|
||||
/* Undocumented. */
|
||||
extern int rl_maybe_save_line PARAMS((void));
|
||||
extern int rl_maybe_unsave_line PARAMS((void));
|
||||
|
@ -560,6 +568,13 @@ extern rl_hook_func_t *rl_pre_input_hook;
|
|||
awaiting character input, or NULL, for no event handling. */
|
||||
extern rl_hook_func_t *rl_event_hook;
|
||||
|
||||
/* The address of a function to call if a read is interrupted by a signal. */
|
||||
extern rl_hook_func_t *rl_signal_event_hook;
|
||||
|
||||
/* The address of a function to call if Readline needs to know whether or not
|
||||
there is data available from the current input source. */
|
||||
extern rl_hook_func_t *rl_input_available_hook;
|
||||
|
||||
/* The address of the function to call to fetch a character from the current
|
||||
Readline input stream */
|
||||
extern rl_getc_func_t *rl_getc_function;
|
||||
|
@ -573,6 +588,10 @@ extern rl_voidfunc_t *rl_deprep_term_function;
|
|||
extern Keymap rl_executing_keymap;
|
||||
extern Keymap rl_binding_keymap;
|
||||
|
||||
extern int rl_executing_key;
|
||||
extern char *rl_executing_keyseq;
|
||||
extern int rl_key_sequence_length;
|
||||
|
||||
/* Display variables. */
|
||||
/* If non-zero, readline will erase the entire line, including any prompt,
|
||||
if the only thing typed on an otherwise-blank line is something bound to
|
||||
|
@ -603,6 +622,10 @@ extern int rl_catch_signals;
|
|||
to do that. */
|
||||
extern int rl_catch_sigwinch;
|
||||
|
||||
/* If non-zero, the readline SIGWINCH handler will modify LINES and
|
||||
COLUMNS in the environment. */
|
||||
extern int rl_change_environment;
|
||||
|
||||
/* Completion variables. */
|
||||
/* Pointer to the generator function for completion_matches ().
|
||||
NULL means to use rl_filename_completion_function (), the default
|
||||
|
@ -686,6 +709,13 @@ extern rl_icppfunc_t *rl_directory_completion_hook;
|
|||
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 for the completer to call
|
||||
before deciding which character to append to a completed name. It should
|
||||
modify the directory name passed as an argument if appropriate, and return
|
||||
non-zero if it modifies the name. This should not worry about dequoting
|
||||
the filename; that has already happened by the time it gets here. */
|
||||
extern rl_icppfunc_t *rl_filename_stat_hook;
|
||||
|
||||
/* If non-zero, this is the address of a function to call when reading
|
||||
directory entries from the filesystem for completion and comparing
|
||||
them to the partial word to be completed. The function should
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* rlconf.h -- readline configuration definitions */
|
||||
|
||||
/* Copyright (C) 1992-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1992-2012 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.
|
||||
|
@ -28,8 +28,12 @@
|
|||
/* Define this to get an indication of file type when listing completions. */
|
||||
#define VISIBLE_STATS
|
||||
|
||||
/* Define this to get support for colors when listing completions and in
|
||||
other places. */
|
||||
#define COLOR_SUPPORT
|
||||
|
||||
/* This definition is needed by readline.c, rltty.c, and signals.c. */
|
||||
/* If on, then readline handles signals in a way that doesn't screw. */
|
||||
/* If on, then readline handles signals in a way that doesn't suck. */
|
||||
#define HANDLE_SIGNALS
|
||||
|
||||
/* Ugly but working hack for binding prefix meta. */
|
||||
|
@ -58,4 +62,8 @@
|
|||
/* Define this if you want the cursor to indicate insert or overwrite mode. */
|
||||
/* #define CURSOR_MODE */
|
||||
|
||||
/* Define this if you want to enable code that talks to the Linux kernel
|
||||
tty auditing system. */
|
||||
#define ENABLE_TTY_AUDIT_SUPPORT
|
||||
|
||||
#endif /* _RLCONF_H_ */
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
for readline. This should be included after any files that define
|
||||
system-specific constants like _POSIX_VERSION or USG. */
|
||||
|
||||
/* 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.
|
||||
|
@ -79,8 +79,8 @@ extern char *strchr (), *strrchr ();
|
|||
#define _rl_stricmp strcasecmp
|
||||
#define _rl_strnicmp strncasecmp
|
||||
#else
|
||||
extern int _rl_stricmp PARAMS((char *, char *));
|
||||
extern int _rl_strnicmp PARAMS((char *, char *, int));
|
||||
extern int _rl_stricmp PARAMS((const char *, const char *));
|
||||
extern int _rl_strnicmp PARAMS((const char *, const char *, int));
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_STRPBRK) && !defined (HAVE_MULTIBYTE)
|
||||
|
@ -148,6 +148,10 @@ extern char *_rl_strpbrk PARAMS((const char *, const char *));
|
|||
: ((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))
|
||||
#endif
|
||||
|
||||
#if !defined (RL_STRLEN)
|
||||
# define RL_STRLEN(s) (((s) && (s)[0]) ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0)
|
||||
#endif
|
||||
|
||||
#if !defined (FREE)
|
||||
# define FREE(x) if (x) free (x)
|
||||
#endif
|
||||
|
|
|
@ -123,6 +123,15 @@ extern int _rl_walphabetic PARAMS((wchar_t));
|
|||
#define MB_INVALIDCH(x) ((x) == (size_t)-1 || (x) == (size_t)-2)
|
||||
#define MB_NULLWCH(x) ((x) == 0)
|
||||
|
||||
/* Unicode combining characters range from U+0300 to U+036F */
|
||||
#define UNICODE_COMBINING_CHAR(x) ((x) >= 768 && (x) <= 879)
|
||||
|
||||
#if defined (WCWIDTH_BROKEN)
|
||||
# define WCWIDTH(wc) ((_rl_utf8locale && UNICODE_COMBINING_CHAR(wc)) ? 0 : wcwidth(wc))
|
||||
#else
|
||||
# define WCWIDTH(wc) wcwidth(wc)
|
||||
#endif
|
||||
|
||||
#else /* !HANDLE_MULTIBYTE */
|
||||
|
||||
#undef MB_LEN_MAX
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* rlprivate.h -- functions and variables global to the readline library,
|
||||
but not intended for use by applications. */
|
||||
|
||||
/* Copyright (C) 1999-2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999-2012 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.
|
||||
|
@ -42,6 +42,12 @@
|
|||
if (_rl_caught_signal) _rl_signal_handler (_rl_caught_signal); \
|
||||
} while (0)
|
||||
|
||||
#define RL_SIG_RECEIVED() (_rl_caught_signal != 0)
|
||||
#define RL_SIGINT_RECEIVED() (_rl_caught_signal == SIGINT)
|
||||
|
||||
#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
|
||||
#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* Global structs undocumented in texinfo manual and not in readline.h *
|
||||
|
@ -86,9 +92,11 @@ typedef struct __rl_search_context
|
|||
int history_pos;
|
||||
int direction;
|
||||
|
||||
int prevc;
|
||||
int lastc;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
char mb[MB_LEN_MAX];
|
||||
char pmb[MB_LEN_MAX];
|
||||
#endif
|
||||
|
||||
char *sline;
|
||||
|
@ -156,6 +164,8 @@ typedef struct __rl_callback_generic_arg
|
|||
|
||||
typedef int _rl_callback_func_t PARAMS((_rl_callback_generic_arg *));
|
||||
|
||||
typedef void _rl_sigcleanup_func_t PARAMS((int, void *));
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* Global functions undocumented in texinfo manual and not in readline.h *
|
||||
|
@ -173,12 +183,14 @@ extern int rl_complete_with_tilde_expansion;
|
|||
#if defined (VISIBLE_STATS)
|
||||
extern int rl_visible_stats;
|
||||
#endif /* VISIBLE_STATS */
|
||||
#if defined (COLOR_SUPPORT)
|
||||
extern int _rl_colored_stats;
|
||||
#endif
|
||||
|
||||
/* readline.c */
|
||||
extern int rl_line_buffer_len;
|
||||
extern int rl_arg_sign;
|
||||
extern int rl_visible_prompt_length;
|
||||
extern int rl_key_sequence_length;
|
||||
extern int rl_byte_oriented;
|
||||
|
||||
/* display.c */
|
||||
|
@ -189,7 +201,7 @@ extern int rl_blink_matching_paren;
|
|||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* Global functions and variables unsed and undocumented *
|
||||
* Global functions and variables unused and undocumented *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
|
@ -240,6 +252,7 @@ extern void _rl_callback_data_dispose PARAMS((_rl_callback_generic_arg *));
|
|||
#endif /* READLINE_CALLBACKS */
|
||||
|
||||
/* bind.c */
|
||||
extern char *_rl_untranslate_macro_value PARAMS((char *, int));
|
||||
|
||||
/* complete.c */
|
||||
extern void _rl_reset_completion_state PARAMS((void));
|
||||
|
@ -248,6 +261,7 @@ extern void _rl_free_match_list PARAMS((char **));
|
|||
|
||||
/* display.c */
|
||||
extern char *_rl_strip_prompt PARAMS((char *));
|
||||
extern void _rl_reset_prompt PARAMS((void));
|
||||
extern void _rl_move_cursor_relative PARAMS((int, const char *));
|
||||
extern void _rl_move_vert PARAMS((int));
|
||||
extern void _rl_save_prompt PARAMS((void));
|
||||
|
@ -282,6 +296,7 @@ extern int _rl_search_getchar PARAMS((_rl_search_cxt *));
|
|||
/* macro.c */
|
||||
extern void _rl_with_macro_input PARAMS((char *));
|
||||
extern int _rl_next_macro_key PARAMS((void));
|
||||
extern int _rl_prev_macro_key PARAMS((void));
|
||||
extern void _rl_push_executing_macro PARAMS((void));
|
||||
extern void _rl_pop_executing_macro PARAMS((void));
|
||||
extern void _rl_add_macro_char PARAMS((int));
|
||||
|
@ -330,6 +345,7 @@ extern void _rl_release_sigwinch PARAMS((void));
|
|||
|
||||
/* terminal.c */
|
||||
extern void _rl_get_screen_size PARAMS((int, int));
|
||||
extern void _rl_sigwinch_resize_terminal PARAMS((void));
|
||||
extern int _rl_init_terminal_io PARAMS((const char *));
|
||||
#ifdef _MINIX
|
||||
extern void _rl_output_character_function PARAMS((int));
|
||||
|
@ -339,6 +355,7 @@ extern int _rl_output_character_function PARAMS((int));
|
|||
extern void _rl_output_some_chars PARAMS((const char *, int));
|
||||
extern int _rl_backspace PARAMS((int));
|
||||
extern void _rl_enable_meta_key PARAMS((void));
|
||||
extern void _rl_disable_meta_key PARAMS((void));
|
||||
extern void _rl_control_keypad PARAMS((int));
|
||||
extern void _rl_set_cursor PARAMS((int, int));
|
||||
|
||||
|
@ -360,6 +377,7 @@ extern int _rl_set_mark_at_pos PARAMS((int));
|
|||
/* undo.c */
|
||||
extern UNDO_LIST *_rl_copy_undo_entry PARAMS((UNDO_LIST *));
|
||||
extern UNDO_LIST *_rl_copy_undo_list PARAMS((UNDO_LIST *));
|
||||
extern void _rl_free_undo_list PARAMS((UNDO_LIST *));
|
||||
|
||||
/* util.c */
|
||||
#if defined (USE_VARARGS) && defined (PREFER_STDARG)
|
||||
|
@ -371,6 +389,7 @@ extern void _rl_ttymsg ();
|
|||
extern void _rl_errmsg ();
|
||||
extern void _rl_trace ();
|
||||
#endif
|
||||
extern void _rl_audit_tty PARAMS((char *));
|
||||
|
||||
extern int _rl_tropen PARAMS((void));
|
||||
|
||||
|
@ -441,6 +460,9 @@ extern int _rl_history_saved_point;
|
|||
|
||||
extern _rl_arg_cxt _rl_argcxt;
|
||||
|
||||
/* nls.c */
|
||||
extern int _rl_utf8locale;
|
||||
|
||||
/* readline.c */
|
||||
extern int _rl_echoing_p;
|
||||
extern int _rl_horizontal_scroll_mode;
|
||||
|
@ -452,6 +474,7 @@ extern int _rl_output_meta_chars;
|
|||
extern int _rl_bind_stty_chars;
|
||||
extern int _rl_revert_all_at_newline;
|
||||
extern int _rl_echo_control_chars;
|
||||
extern int _rl_show_mode_in_prompt;
|
||||
extern char *_rl_comment_begin;
|
||||
extern unsigned char _rl_parsing_conditionalized_out;
|
||||
extern Keymap _rl_keymap;
|
||||
|
@ -461,6 +484,9 @@ extern int _rl_last_command_was_kill;
|
|||
extern int _rl_eof_char;
|
||||
extern procenv_t _rl_top_level;
|
||||
extern _rl_keyseq_cxt *_rl_kscxt;
|
||||
extern int _rl_keyseq_timeout;
|
||||
|
||||
extern int _rl_executing_keyseq_size;
|
||||
|
||||
/* search.c */
|
||||
extern _rl_search_cxt *_rl_nscxt;
|
||||
|
@ -469,6 +495,9 @@ extern _rl_search_cxt *_rl_nscxt;
|
|||
extern int _rl_interrupt_immediately;
|
||||
extern int volatile _rl_caught_signal;
|
||||
|
||||
extern _rl_sigcleanup_func_t *_rl_sigcleanup;
|
||||
extern void *_rl_sigcleanarg;
|
||||
|
||||
extern int _rl_echoctl;
|
||||
|
||||
extern int _rl_intr_char;
|
||||
|
|
|
@ -42,4 +42,16 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/* Moved from config.h.in because readline.h:rl_message depends on these
|
||||
defines. */
|
||||
#if defined (__STDC__) && defined (HAVE_STDARG_H)
|
||||
# define PREFER_STDARG
|
||||
# define USE_VARARGS
|
||||
#else
|
||||
# if defined (HAVE_VARARGS_H)
|
||||
# define PREFER_VARARGS
|
||||
# define USE_VARARGS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* !_RL_STDC_H_ */
|
||||
|
|
|
@ -121,7 +121,7 @@ static int set_tty_settings PARAMS((int, TIOTYPE *));
|
|||
|
||||
static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
|
||||
|
||||
static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
|
||||
static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t *));
|
||||
|
||||
static void
|
||||
save_tty_chars (tiop)
|
||||
|
@ -341,7 +341,7 @@ static int set_tty_settings PARAMS((int, TIOTYPE *));
|
|||
|
||||
static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
|
||||
|
||||
static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
|
||||
static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t *));
|
||||
static void _rl_bind_tty_special_chars PARAMS((Keymap, TIOTYPE));
|
||||
|
||||
#if defined (FLUSHO)
|
||||
|
@ -528,10 +528,10 @@ prepare_terminal_settings (meta_flag, oldtio, tiop)
|
|||
|
||||
#if defined (USE_XON_XOFF)
|
||||
#if defined (IXANY)
|
||||
tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
|
||||
tiop->c_iflag &= ~(IXON | IXANY);
|
||||
#else
|
||||
/* `strict' Posix systems do not define IXANY. */
|
||||
tiop->c_iflag &= ~(IXON | IXOFF);
|
||||
tiop->c_iflag &= ~IXON;
|
||||
#endif /* IXANY */
|
||||
#endif /* USE_XON_XOFF */
|
||||
|
||||
|
@ -678,7 +678,7 @@ rl_deprep_terminal ()
|
|||
/* Try to keep this function from being interrupted. */
|
||||
_rl_block_sigint ();
|
||||
|
||||
tty = rl_instream ? fileno (rl_instream) : fileno (stdout);
|
||||
tty = rl_instream ? fileno (rl_instream) : fileno (stdin);
|
||||
|
||||
if (_rl_enable_keypad)
|
||||
_rl_control_keypad (0);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* rltypedefs.h -- Type declarations for readline functions. */
|
||||
|
||||
/* Copyright (C) 2000-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2000-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.
|
||||
|
@ -26,18 +26,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Old-style */
|
||||
|
||||
#if !defined (_FUNCTION_DEF)
|
||||
# define _FUNCTION_DEF
|
||||
|
||||
typedef int Function ();
|
||||
typedef void VFunction ();
|
||||
typedef char *CPFunction ();
|
||||
typedef char **CPPFunction ();
|
||||
|
||||
#endif /* _FUNCTION_DEF */
|
||||
|
||||
/* New style. */
|
||||
|
||||
#if !defined (_RL_FUNCTION_TYPEDEF)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* search.c - code for non-incremental searching in emacs and vi modes. */
|
||||
|
||||
/* Copyright (C) 1992-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1992-2013 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.
|
||||
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include "readline.h"
|
||||
#include "history.h"
|
||||
#include "histlib.h"
|
||||
|
||||
#include "rlprivate.h"
|
||||
#include "xmalloc.h"
|
||||
|
@ -66,6 +67,8 @@ static char *prev_line_found = (char *) NULL;
|
|||
|
||||
static int rl_history_search_len;
|
||||
static int rl_history_search_pos;
|
||||
static int rl_history_search_flags;
|
||||
|
||||
static char *history_search_string;
|
||||
static int history_string_size;
|
||||
|
||||
|
@ -74,7 +77,7 @@ static int noninc_search_from_pos PARAMS((char *, int, int));
|
|||
static int noninc_dosearch PARAMS((char *, int));
|
||||
static int noninc_search PARAMS((int, int));
|
||||
static int rl_history_search_internal PARAMS((int, int));
|
||||
static void rl_history_search_reinit PARAMS((void));
|
||||
static void rl_history_search_reinit PARAMS((int));
|
||||
|
||||
static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int));
|
||||
static int _rl_nsearch_cleanup PARAMS((_rl_search_cxt *, int));
|
||||
|
@ -169,7 +172,8 @@ noninc_dosearch (string, dir)
|
|||
|
||||
oldpos = where_history ();
|
||||
history_set_pos (noninc_history_pos);
|
||||
entry = current_history ();
|
||||
entry = current_history (); /* will never be NULL after successful search */
|
||||
|
||||
#if defined (VI_MODE)
|
||||
if (rl_editing_mode != vi_mode)
|
||||
#endif
|
||||
|
@ -210,7 +214,7 @@ _rl_nsearch_init (dir, pchar)
|
|||
rl_end = rl_point = 0;
|
||||
|
||||
p = _rl_make_prompt_for_search (pchar ? pchar : ':');
|
||||
rl_message ("%s", p, 0);
|
||||
rl_message ("%s", p);
|
||||
xfree (p);
|
||||
|
||||
RL_SETSTATE(RL_STATE_NSEARCH);
|
||||
|
@ -453,15 +457,19 @@ rl_history_search_internal (count, dir)
|
|||
{
|
||||
HIST_ENTRY *temp;
|
||||
int ret, oldpos;
|
||||
char *t;
|
||||
|
||||
rl_maybe_save_line ();
|
||||
temp = (HIST_ENTRY *)NULL;
|
||||
|
||||
/* Search COUNT times through the history for a line whose prefix
|
||||
matches history_search_string. When this loop finishes, TEMP,
|
||||
if non-null, is the history line to copy into the line buffer. */
|
||||
/* Search COUNT times through the history for a line matching
|
||||
history_search_string. If history_search_string[0] == '^', the
|
||||
line must match from the start; otherwise any substring can match.
|
||||
When this loop finishes, TEMP, if non-null, is the history line to
|
||||
copy into the line buffer. */
|
||||
while (count)
|
||||
{
|
||||
RL_CHECK_SIGNALS ();
|
||||
ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
|
||||
if (ret == -1)
|
||||
break;
|
||||
|
@ -470,7 +478,7 @@ rl_history_search_internal (count, dir)
|
|||
rl_history_search_pos = ret;
|
||||
oldpos = where_history ();
|
||||
history_set_pos (rl_history_search_pos);
|
||||
temp = current_history ();
|
||||
temp = current_history (); /* will never be NULL after successful search */
|
||||
history_set_pos (oldpos);
|
||||
|
||||
/* Don't find multiple instances of the same line. */
|
||||
|
@ -505,35 +513,49 @@ rl_history_search_internal (count, dir)
|
|||
/* Copy the line we found into the current line buffer. */
|
||||
make_history_line_current (temp);
|
||||
|
||||
rl_point = rl_history_search_len;
|
||||
if (rl_history_search_flags & ANCHORED_SEARCH)
|
||||
rl_point = rl_history_search_len; /* easy case */
|
||||
else
|
||||
{
|
||||
t = strstr (rl_line_buffer, history_search_string);
|
||||
rl_point = t ? (int)(t - rl_line_buffer) + rl_history_search_len : rl_end;
|
||||
}
|
||||
rl_mark = rl_end;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rl_history_search_reinit ()
|
||||
rl_history_search_reinit (flags)
|
||||
int flags;
|
||||
{
|
||||
int sind;
|
||||
|
||||
rl_history_search_pos = where_history ();
|
||||
rl_history_search_len = rl_point;
|
||||
rl_history_search_flags = flags;
|
||||
|
||||
prev_line_found = (char *)NULL;
|
||||
if (rl_point)
|
||||
{
|
||||
/* Allocate enough space for anchored and non-anchored searches */
|
||||
if (rl_history_search_len >= history_string_size - 2)
|
||||
{
|
||||
history_string_size = rl_history_search_len + 2;
|
||||
history_search_string = (char *)xrealloc (history_search_string, history_string_size);
|
||||
}
|
||||
history_search_string[0] = '^';
|
||||
strncpy (history_search_string + 1, rl_line_buffer, rl_point);
|
||||
history_search_string[rl_point + 1] = '\0';
|
||||
sind = 0;
|
||||
if (flags & ANCHORED_SEARCH)
|
||||
history_search_string[sind++] = '^';
|
||||
strncpy (history_search_string + sind, rl_line_buffer, rl_point);
|
||||
history_search_string[rl_point + sind] = '\0';
|
||||
}
|
||||
_rl_free_saved_history_line ();
|
||||
}
|
||||
|
||||
/* Search forward in the history for the string of characters
|
||||
from the start of the line to rl_point. This is a non-incremental
|
||||
search. */
|
||||
search. The search is anchored to the beginning of the history line. */
|
||||
int
|
||||
rl_history_search_forward (count, ignore)
|
||||
int count, ignore;
|
||||
|
@ -543,7 +565,7 @@ rl_history_search_forward (count, ignore)
|
|||
|
||||
if (rl_last_func != rl_history_search_forward &&
|
||||
rl_last_func != rl_history_search_backward)
|
||||
rl_history_search_reinit ();
|
||||
rl_history_search_reinit (ANCHORED_SEARCH);
|
||||
|
||||
if (rl_history_search_len == 0)
|
||||
return (rl_get_next_history (count, ignore));
|
||||
|
@ -562,7 +584,46 @@ rl_history_search_backward (count, ignore)
|
|||
|
||||
if (rl_last_func != rl_history_search_forward &&
|
||||
rl_last_func != rl_history_search_backward)
|
||||
rl_history_search_reinit ();
|
||||
rl_history_search_reinit (ANCHORED_SEARCH);
|
||||
|
||||
if (rl_history_search_len == 0)
|
||||
return (rl_get_previous_history (count, ignore));
|
||||
return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
|
||||
}
|
||||
|
||||
/* Search forward in the history for the string of characters
|
||||
from the start of the line to rl_point. This is a non-incremental
|
||||
search. The search succeeds if the search string is present anywhere
|
||||
in the history line. */
|
||||
int
|
||||
rl_history_substr_search_forward (count, ignore)
|
||||
int count, ignore;
|
||||
{
|
||||
if (count == 0)
|
||||
return (0);
|
||||
|
||||
if (rl_last_func != rl_history_substr_search_forward &&
|
||||
rl_last_func != rl_history_substr_search_backward)
|
||||
rl_history_search_reinit (NON_ANCHORED_SEARCH);
|
||||
|
||||
if (rl_history_search_len == 0)
|
||||
return (rl_get_next_history (count, ignore));
|
||||
return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
|
||||
}
|
||||
|
||||
/* Search backward through the history for the string of characters
|
||||
from the start of the line to rl_point. This is a non-incremental
|
||||
search. */
|
||||
int
|
||||
rl_history_substr_search_backward (count, ignore)
|
||||
int count, ignore;
|
||||
{
|
||||
if (count == 0)
|
||||
return (0);
|
||||
|
||||
if (rl_last_func != rl_history_substr_search_forward &&
|
||||
rl_last_func != rl_history_substr_search_backward)
|
||||
rl_history_search_reinit (NON_ANCHORED_SEARCH);
|
||||
|
||||
if (rl_history_search_len == 0)
|
||||
return (rl_get_previous_history (count, ignore));
|
||||
|
|
|
@ -59,6 +59,8 @@
|
|||
|
||||
#include "rlstdc.h"
|
||||
#include "rlshell.h"
|
||||
#include "rldefs.h"
|
||||
|
||||
#include "xmalloc.h"
|
||||
|
||||
#if defined (HAVE_GETPWUID) && !defined (HAVE_GETPW_DECLS)
|
||||
|
@ -120,31 +122,27 @@ sh_single_quote (string)
|
|||
|
||||
/* Set the environment variables LINES and COLUMNS to lines and cols,
|
||||
respectively. */
|
||||
static char setenv_buf[INT_STRLEN_BOUND (int) + 1];
|
||||
static char putenv_buf1[INT_STRLEN_BOUND (int) + 6 + 1]; /* sizeof("LINES=") == 6 */
|
||||
static char putenv_buf2[INT_STRLEN_BOUND (int) + 8 + 1]; /* sizeof("COLUMNS=") == 8 */
|
||||
|
||||
void
|
||||
sh_set_lines_and_columns (lines, cols)
|
||||
int lines, cols;
|
||||
{
|
||||
char *b;
|
||||
|
||||
#if defined (HAVE_SETENV)
|
||||
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
|
||||
sprintf (b, "%d", lines);
|
||||
setenv ("LINES", b, 1);
|
||||
xfree (b);
|
||||
sprintf (setenv_buf, "%d", lines);
|
||||
setenv ("LINES", setenv_buf, 1);
|
||||
|
||||
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
|
||||
sprintf (b, "%d", cols);
|
||||
setenv ("COLUMNS", b, 1);
|
||||
xfree (b);
|
||||
sprintf (setenv_buf, "%d", cols);
|
||||
setenv ("COLUMNS", setenv_buf, 1);
|
||||
#else /* !HAVE_SETENV */
|
||||
# if defined (HAVE_PUTENV)
|
||||
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("LINES=") + 1);
|
||||
sprintf (b, "LINES=%d", lines);
|
||||
putenv (b);
|
||||
sprintf (putenv_buf1, "LINES=%d", lines);
|
||||
putenv (putenv_buf1);
|
||||
|
||||
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("COLUMNS=") + 1);
|
||||
sprintf (b, "COLUMNS=%d", cols);
|
||||
putenv (b);
|
||||
sprintf (putenv_buf2, "COLUMNS=%d", cols);
|
||||
putenv (putenv_buf2);
|
||||
# endif /* HAVE_PUTENV */
|
||||
#endif /* !HAVE_SETENV */
|
||||
}
|
||||
|
@ -159,15 +157,27 @@ sh_get_env_value (varname)
|
|||
char *
|
||||
sh_get_home_dir ()
|
||||
{
|
||||
char *home_dir;
|
||||
static char *home_dir = (char *)NULL;
|
||||
struct passwd *entry;
|
||||
|
||||
if (home_dir)
|
||||
return (home_dir);
|
||||
|
||||
home_dir = (char *)NULL;
|
||||
#if defined (HAVE_GETPWUID)
|
||||
# if defined (__TANDEM)
|
||||
entry = getpwnam (getlogin ());
|
||||
# else
|
||||
entry = getpwuid (getuid ());
|
||||
# endif
|
||||
if (entry)
|
||||
home_dir = entry->pw_dir;
|
||||
home_dir = savestring (entry->pw_dir);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_GETPWENT)
|
||||
endpwent (); /* some systems need this */
|
||||
#endif
|
||||
|
||||
return (home_dir);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* signals.c -- signal handling support 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.
|
||||
|
@ -80,6 +80,7 @@ typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt
|
|||
|
||||
static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
|
||||
static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
|
||||
static void rl_maybe_restore_sighandler PARAMS((int, sighandler_cxt *));
|
||||
|
||||
static RETSIGTYPE rl_signal_handler PARAMS((int));
|
||||
static RETSIGTYPE _rl_handle_signal PARAMS((int));
|
||||
|
@ -87,7 +88,7 @@ static RETSIGTYPE _rl_handle_signal PARAMS((int));
|
|||
/* Exported variables for use by applications. */
|
||||
|
||||
/* If non-zero, readline will install its own signal handlers for
|
||||
SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
|
||||
SIGINT, SIGTERM, SIGHUP, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
|
||||
int rl_catch_signals = 1;
|
||||
|
||||
/* If non-zero, readline will install a signal handler for SIGWINCH. */
|
||||
|
@ -118,7 +119,7 @@ static int sigwinch_set_flag;
|
|||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
static sighandler_cxt old_int, old_term, old_alrm, old_quit;
|
||||
static sighandler_cxt old_int, old_term, old_hup, old_alrm, old_quit;
|
||||
#if defined (SIGTSTP)
|
||||
static sighandler_cxt old_tstp, old_ttou, old_ttin;
|
||||
#endif
|
||||
|
@ -126,6 +127,9 @@ static sighandler_cxt old_tstp, old_ttou, old_ttin;
|
|||
static sighandler_cxt old_winch;
|
||||
#endif
|
||||
|
||||
_rl_sigcleanup_func_t *_rl_sigcleanup;
|
||||
void *_rl_sigcleanarg;
|
||||
|
||||
/* Readline signal handler functions. */
|
||||
|
||||
/* Called from RL_CHECK_SIGNALS() macro */
|
||||
|
@ -135,7 +139,21 @@ _rl_signal_handler (sig)
|
|||
{
|
||||
_rl_caught_signal = 0; /* XXX */
|
||||
|
||||
_rl_handle_signal (sig);
|
||||
#if defined (SIGWINCH)
|
||||
if (sig == SIGWINCH)
|
||||
{
|
||||
rl_resize_terminal ();
|
||||
/* XXX - experimental for now */
|
||||
/* Call a signal hook because though we called the original signal handler
|
||||
in rl_sigwinch_handler below, we will not resend the signal to
|
||||
ourselves. */
|
||||
if (rl_signal_event_hook)
|
||||
(*rl_signal_event_hook) ();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
_rl_handle_signal (sig);
|
||||
|
||||
SIGHANDLER_RETURN;
|
||||
}
|
||||
|
||||
|
@ -143,7 +161,7 @@ static RETSIGTYPE
|
|||
rl_signal_handler (sig)
|
||||
int sig;
|
||||
{
|
||||
if (_rl_interrupt_immediately || RL_ISSTATE(RL_STATE_CALLBACK))
|
||||
if (_rl_interrupt_immediately)
|
||||
{
|
||||
_rl_interrupt_immediately = 0;
|
||||
_rl_handle_signal (sig);
|
||||
|
@ -181,6 +199,15 @@ _rl_handle_signal (sig)
|
|||
rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
|
||||
#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
|
||||
|
||||
/* If there's a sig cleanup function registered, call it and `deregister'
|
||||
the cleanup function to avoid multiple calls */
|
||||
if (_rl_sigcleanup)
|
||||
{
|
||||
(*_rl_sigcleanup) (sig, _rl_sigcleanarg);
|
||||
_rl_sigcleanup = 0;
|
||||
_rl_sigcleanarg = 0;
|
||||
}
|
||||
|
||||
switch (sig)
|
||||
{
|
||||
case SIGINT:
|
||||
|
@ -189,6 +216,7 @@ _rl_handle_signal (sig)
|
|||
/* FALLTHROUGH */
|
||||
|
||||
case SIGTERM:
|
||||
case SIGHUP:
|
||||
#if defined (SIGTSTP)
|
||||
case SIGTSTP:
|
||||
case SIGTTOU:
|
||||
|
@ -232,7 +260,7 @@ _rl_handle_signal (sig)
|
|||
# endif /* HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
rl_reset_after_signal ();
|
||||
rl_reset_after_signal ();
|
||||
}
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_SIGHANDLER);
|
||||
|
@ -257,7 +285,7 @@ rl_sigwinch_handler (sig)
|
|||
#endif
|
||||
|
||||
RL_SETSTATE(RL_STATE_SIGHANDLER);
|
||||
rl_resize_terminal ();
|
||||
_rl_caught_signal = sig;
|
||||
|
||||
/* If another sigwinch handler has been installed, call it. */
|
||||
oh = (SigHandler *)old_winch.sa_handler;
|
||||
|
@ -317,6 +345,8 @@ rl_set_sighandler (sig, handler, ohandler)
|
|||
return (ohandler->sa_handler);
|
||||
}
|
||||
|
||||
/* Set disposition of SIG to HANDLER, returning old state in OHANDLER. Don't
|
||||
change disposition if OHANDLER indicates the signal was ignored. */
|
||||
static void
|
||||
rl_maybe_set_sighandler (sig, handler, ohandler)
|
||||
int sig;
|
||||
|
@ -327,11 +357,29 @@ rl_maybe_set_sighandler (sig, handler, ohandler)
|
|||
SigHandler *oh;
|
||||
|
||||
sigemptyset (&dummy.sa_mask);
|
||||
dummy.sa_flags = 0;
|
||||
oh = rl_set_sighandler (sig, handler, ohandler);
|
||||
if (oh == (SigHandler *)SIG_IGN)
|
||||
rl_sigaction (sig, ohandler, &dummy);
|
||||
}
|
||||
|
||||
/* Set the disposition of SIG to HANDLER, if HANDLER->sa_handler indicates the
|
||||
signal was not being ignored. MUST only be called for signals whose
|
||||
disposition was changed using rl_maybe_set_sighandler or for which the
|
||||
SIG_IGN check was performed inline (e.g., SIGALRM below). */
|
||||
static void
|
||||
rl_maybe_restore_sighandler (sig, handler)
|
||||
int sig;
|
||||
sighandler_cxt *handler;
|
||||
{
|
||||
sighandler_cxt dummy;
|
||||
|
||||
sigemptyset (&dummy.sa_mask);
|
||||
dummy.sa_flags = 0;
|
||||
if (handler->sa_handler != SIG_IGN)
|
||||
rl_sigaction (sig, handler, &dummy);
|
||||
}
|
||||
|
||||
int
|
||||
rl_set_signals ()
|
||||
{
|
||||
|
@ -349,6 +397,7 @@ rl_set_signals ()
|
|||
|
||||
sigaddset (&bset, SIGINT);
|
||||
sigaddset (&bset, SIGTERM);
|
||||
sigaddset (&bset, SIGHUP);
|
||||
#if defined (SIGQUIT)
|
||||
sigaddset (&bset, SIGQUIT);
|
||||
#endif
|
||||
|
@ -377,6 +426,7 @@ rl_set_signals ()
|
|||
|
||||
rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
|
||||
rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
|
||||
rl_maybe_set_sighandler (SIGHUP, rl_signal_handler, &old_hup);
|
||||
#if defined (SIGQUIT)
|
||||
rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
|
||||
#endif
|
||||
|
@ -434,25 +484,31 @@ rl_clear_signals ()
|
|||
{
|
||||
sigemptyset (&dummy.sa_mask);
|
||||
|
||||
rl_sigaction (SIGINT, &old_int, &dummy);
|
||||
rl_sigaction (SIGTERM, &old_term, &dummy);
|
||||
/* Since rl_maybe_set_sighandler doesn't override a SIG_IGN handler,
|
||||
we should in theory not have to restore a handler where
|
||||
old_xxx.sa_handler == SIG_IGN. That's what rl_maybe_restore_sighandler
|
||||
does. Fewer system calls should reduce readline's per-line
|
||||
overhead */
|
||||
rl_maybe_restore_sighandler (SIGINT, &old_int);
|
||||
rl_maybe_restore_sighandler (SIGTERM, &old_term);
|
||||
rl_maybe_restore_sighandler (SIGHUP, &old_hup);
|
||||
#if defined (SIGQUIT)
|
||||
rl_sigaction (SIGQUIT, &old_quit, &dummy);
|
||||
rl_maybe_restore_sighandler (SIGQUIT, &old_quit);
|
||||
#endif
|
||||
#if defined (SIGALRM)
|
||||
rl_sigaction (SIGALRM, &old_alrm, &dummy);
|
||||
rl_maybe_restore_sighandler (SIGALRM, &old_alrm);
|
||||
#endif
|
||||
|
||||
#if defined (SIGTSTP)
|
||||
rl_sigaction (SIGTSTP, &old_tstp, &dummy);
|
||||
rl_maybe_restore_sighandler (SIGTSTP, &old_tstp);
|
||||
#endif /* SIGTSTP */
|
||||
|
||||
#if defined (SIGTTOU)
|
||||
rl_sigaction (SIGTTOU, &old_ttou, &dummy);
|
||||
rl_maybe_restore_sighandler (SIGTTOU, &old_ttou);
|
||||
#endif /* SIGTTOU */
|
||||
|
||||
#if defined (SIGTTIN)
|
||||
rl_sigaction (SIGTTIN, &old_ttin, &dummy);
|
||||
rl_maybe_restore_sighandler (SIGTTIN, &old_ttin);
|
||||
#endif /* SIGTTIN */
|
||||
|
||||
signals_set_flag = 0;
|
||||
|
@ -540,21 +596,6 @@ _rl_block_sigint ()
|
|||
if (sigint_blocked)
|
||||
return;
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigemptyset (&sigint_set);
|
||||
sigemptyset (&sigint_oset);
|
||||
sigaddset (&sigint_set, SIGINT);
|
||||
sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
sigint_oldmask = sigblock (sigmask (SIGINT));
|
||||
# else /* !HAVE_BSD_SIGNALS */
|
||||
# if defined (HAVE_USG_SIGHOLD)
|
||||
sighold (SIGINT);
|
||||
# endif /* HAVE_USG_SIGHOLD */
|
||||
# endif /* !HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
sigint_blocked = 1;
|
||||
}
|
||||
|
||||
|
@ -565,19 +606,8 @@ _rl_release_sigint ()
|
|||
if (sigint_blocked == 0)
|
||||
return;
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
|
||||
#else
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
sigsetmask (sigint_oldmask);
|
||||
# else /* !HAVE_BSD_SIGNALS */
|
||||
# if defined (HAVE_USG_SIGHOLD)
|
||||
sigrelse (SIGINT);
|
||||
# endif /* HAVE_USG_SIGHOLD */
|
||||
# endif /* !HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
sigint_blocked = 0;
|
||||
RL_CHECK_SIGNALS ();
|
||||
}
|
||||
|
||||
/* Cause SIGWINCH to not be delivered until the corresponding call to
|
||||
|
@ -588,6 +618,8 @@ _rl_block_sigwinch ()
|
|||
if (sigwinch_blocked)
|
||||
return;
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigemptyset (&sigwinch_set);
|
||||
sigemptyset (&sigwinch_oset);
|
||||
|
@ -603,6 +635,8 @@ _rl_block_sigwinch ()
|
|||
# endif /* !HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
#endif /* SIGWINCH */
|
||||
|
||||
sigwinch_blocked = 1;
|
||||
}
|
||||
|
||||
|
@ -613,6 +647,8 @@ _rl_release_sigwinch ()
|
|||
if (sigwinch_blocked == 0)
|
||||
return;
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &sigwinch_oset, (sigset_t *)NULL);
|
||||
#else
|
||||
|
@ -625,6 +661,8 @@ _rl_release_sigwinch ()
|
|||
# endif /* !HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
#endif /* SIGWINCH */
|
||||
|
||||
sigwinch_blocked = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,10 @@
|
|||
# include <sys/ioctl.h>
|
||||
#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
|
||||
|
||||
#ifdef __MSDOS__
|
||||
# include <pc.h>
|
||||
#endif
|
||||
|
||||
#include "rltty.h"
|
||||
#include "tcap.h"
|
||||
|
||||
|
@ -77,22 +81,25 @@ static void _win_get_screensize PARAMS((int *, int *));
|
|||
static void _emx_get_screensize PARAMS((int *, int *));
|
||||
#endif
|
||||
|
||||
#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
|
||||
#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
|
||||
|
||||
/* If the calling application sets this to a non-zero value, readline will
|
||||
use the $LINES and $COLUMNS environment variables to set its idea of the
|
||||
window size before interrogating the kernel. */
|
||||
/* If the calling application sets this to a non-zero value, readline will
|
||||
use the $LINES and $COLUMNS environment variables to set its idea of the
|
||||
window size before interrogating the kernel. */
|
||||
int rl_prefer_env_winsize = 0;
|
||||
|
||||
/* If this is non-zero, readline will set LINES and COLUMNS in the
|
||||
environment when it handles SIGWINCH. */
|
||||
int rl_change_environment = 1;
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Terminal and Termcap */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
#ifndef __MSDOS__
|
||||
static char *term_buffer = (char *)NULL;
|
||||
static char *term_string_buffer = (char *)NULL;
|
||||
#endif
|
||||
|
||||
static int tcap_initialized;
|
||||
|
||||
|
@ -264,7 +271,10 @@ _rl_get_screen_size (tty, ignore_env)
|
|||
if (_rl_screenwidth <= 0)
|
||||
_rl_screenwidth = wc;
|
||||
|
||||
#if !defined (__DJGPP__)
|
||||
#if defined (__DJGPP__)
|
||||
if (_rl_screenwidth <= 0)
|
||||
_rl_screenwidth = ScreenCols ();
|
||||
#else
|
||||
if (_rl_screenwidth <= 0 && term_string_buffer)
|
||||
_rl_screenwidth = tgetnum ("co");
|
||||
#endif
|
||||
|
@ -280,7 +290,10 @@ _rl_get_screen_size (tty, ignore_env)
|
|||
if (_rl_screenheight <= 0)
|
||||
_rl_screenheight = wr;
|
||||
|
||||
#if !defined (__DJGPP__)
|
||||
#if defined (__DJGPP__)
|
||||
if (_rl_screenheight <= 0)
|
||||
_rl_screenheight = ScreenRows ();
|
||||
#else
|
||||
if (_rl_screenheight <= 0 && term_string_buffer)
|
||||
_rl_screenheight = tgetnum ("li");
|
||||
#endif
|
||||
|
@ -296,7 +309,8 @@ _rl_get_screen_size (tty, ignore_env)
|
|||
/* If we're being compiled as part of bash, set the environment
|
||||
variables $LINES and $COLUMNS to new values. Otherwise, just
|
||||
do a pair of putenv () or setenv () calls. */
|
||||
sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
|
||||
if (rl_change_environment)
|
||||
sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
|
||||
|
||||
if (_rl_term_autowrap == 0)
|
||||
_rl_screenwidth--;
|
||||
|
@ -346,7 +360,13 @@ rl_reset_screen_size ()
|
|||
{
|
||||
_rl_get_screen_size (fileno (rl_instream), 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_rl_sigwinch_resize_terminal ()
|
||||
{
|
||||
_rl_get_screen_size (fileno (rl_instream), 1);
|
||||
}
|
||||
|
||||
void
|
||||
rl_resize_terminal ()
|
||||
{
|
||||
|
@ -432,6 +452,23 @@ _rl_init_terminal_io (terminal_name)
|
|||
if (term == 0)
|
||||
term = "dumb";
|
||||
|
||||
#ifdef __MSDOS__
|
||||
_rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
|
||||
_rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
|
||||
_rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
|
||||
_rl_term_mm = _rl_term_mo = (char *)NULL;
|
||||
_rl_terminal_can_insert = term_has_meta = _rl_term_autowrap = 0;
|
||||
_rl_term_cr = "\r";
|
||||
_rl_term_clreol = _rl_term_clrpag = _rl_term_backspace = (char *)NULL;
|
||||
_rl_term_goto = _rl_term_pc = _rl_term_ip = (char *)NULL;
|
||||
_rl_term_ks = _rl_term_ke =_rl_term_vs = _rl_term_ve = (char *)NULL;
|
||||
_rl_term_kh = _rl_term_kH = _rl_term_at7 = _rl_term_kI = (char *)NULL;
|
||||
#if defined(HACK_TERMCAP_MOTION)
|
||||
_rl_term_forward_char = (char *)NULL;
|
||||
#endif
|
||||
|
||||
_rl_get_screen_size (tty, 0);
|
||||
#else /* !__MSDOS__ */
|
||||
/* I've separated this out for later work on not calling tgetent at all
|
||||
if the calling application has supplied a custom redisplay function,
|
||||
(and possibly if the application has supplied a custom input function). */
|
||||
|
@ -531,6 +568,7 @@ _rl_init_terminal_io (terminal_name)
|
|||
term_has_meta = tgetflag ("km") != 0;
|
||||
if (term_has_meta == 0)
|
||||
_rl_term_mm = _rl_term_mo = (char *)NULL;
|
||||
#endif /* !__MSDOS__ */
|
||||
|
||||
/* Attempt to find and bind the arrow keys. Do not override already
|
||||
bound keys in an overzealous attempt, however. */
|
||||
|
@ -628,10 +666,12 @@ _rl_backspace (count)
|
|||
{
|
||||
register int i;
|
||||
|
||||
#ifndef __MSDOS__
|
||||
if (_rl_term_backspace)
|
||||
for (i = 0; i < count; i++)
|
||||
tputs (_rl_term_backspace, 1, _rl_output_character_function);
|
||||
else
|
||||
#endif
|
||||
for (i = 0; i < count; i++)
|
||||
putc ('\b', _rl_out_stream);
|
||||
return 0;
|
||||
|
@ -663,7 +703,11 @@ rl_ding ()
|
|||
case VISIBLE_BELL:
|
||||
if (_rl_visible_bell)
|
||||
{
|
||||
#ifdef __DJGPP__
|
||||
ScreenVisualBell ();
|
||||
#else
|
||||
tputs (_rl_visible_bell, 1, _rl_output_character_function);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
@ -683,12 +727,29 @@ rl_ding ()
|
|||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
static int enabled_meta = 0; /* flag indicating we enabled meta mode */
|
||||
|
||||
void
|
||||
_rl_enable_meta_key ()
|
||||
{
|
||||
#if !defined (__DJGPP__)
|
||||
if (term_has_meta && _rl_term_mm)
|
||||
tputs (_rl_term_mm, 1, _rl_output_character_function);
|
||||
{
|
||||
tputs (_rl_term_mm, 1, _rl_output_character_function);
|
||||
enabled_meta = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
_rl_disable_meta_key ()
|
||||
{
|
||||
#if !defined (__DJGPP__)
|
||||
if (term_has_meta && _rl_term_mo && enabled_meta)
|
||||
{
|
||||
tputs (_rl_term_mo, 1, _rl_output_character_function);
|
||||
enabled_meta = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -718,6 +779,7 @@ void
|
|||
_rl_set_cursor (im, force)
|
||||
int im, force;
|
||||
{
|
||||
#ifndef __MSDOS__
|
||||
if (_rl_term_ve && _rl_term_vs)
|
||||
{
|
||||
if (force || im != rl_insert_mode)
|
||||
|
@ -728,4 +790,5 @@ _rl_set_cursor (im, force)
|
|||
tputs (_rl_term_ve, 1, _rl_output_character_function);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -240,7 +240,7 @@ rl_replace_line (text, clear_undo)
|
|||
this is the same as rl_end.
|
||||
|
||||
Any command that is called interactively receives two arguments.
|
||||
The first is a count: the numeric arg pased to this command.
|
||||
The first is a count: the numeric arg passed to this command.
|
||||
The second is the key which invoked this command.
|
||||
*/
|
||||
|
||||
|
@ -826,7 +826,7 @@ _rl_insert_char (count, c)
|
|||
pending characters that are bound to rl_insert, and insert
|
||||
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 ())
|
||||
if ((RL_ISSTATE (RL_STATE_MACROINPUT) == 0) && _rl_pushed_input_available ())
|
||||
_rl_insert_typein (c);
|
||||
else
|
||||
{
|
||||
|
@ -908,6 +908,9 @@ _rl_insert_next (count)
|
|||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
if (RL_ISSTATE (RL_STATE_MACRODEF))
|
||||
_rl_add_macro_char (c);
|
||||
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
|
||||
_rl_restore_tty_signals ();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* readline.c -- a general facility for reading lines of input
|
||||
with emacs style editing and completion. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2012 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.
|
||||
|
@ -101,6 +101,25 @@ rl_add_undo (what, start, end, text)
|
|||
rl_undo_list = temp;
|
||||
}
|
||||
|
||||
/* Free an UNDO_LIST */
|
||||
void
|
||||
_rl_free_undo_list (ul)
|
||||
UNDO_LIST *ul;
|
||||
{
|
||||
UNDO_LIST *release;
|
||||
|
||||
while (ul)
|
||||
{
|
||||
release = ul;
|
||||
ul = ul->next;
|
||||
|
||||
if (release->what == UNDO_DELETE)
|
||||
xfree (release->text);
|
||||
|
||||
xfree (release);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the existing undo list. */
|
||||
void
|
||||
rl_free_undo_list ()
|
||||
|
@ -108,16 +127,7 @@ rl_free_undo_list ()
|
|||
UNDO_LIST *release, *orig_list;
|
||||
|
||||
orig_list = rl_undo_list;
|
||||
while (rl_undo_list)
|
||||
{
|
||||
release = rl_undo_list;
|
||||
rl_undo_list = rl_undo_list->next;
|
||||
|
||||
if (release->what == UNDO_DELETE)
|
||||
xfree (release->text);
|
||||
|
||||
xfree (release);
|
||||
}
|
||||
_rl_free_undo_list (rl_undo_list);
|
||||
rl_undo_list = (UNDO_LIST *)NULL;
|
||||
replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
|
||||
}
|
||||
|
@ -168,6 +178,7 @@ rl_do_undo ()
|
|||
{
|
||||
UNDO_LIST *release;
|
||||
int waiting_for_begin, start, end;
|
||||
HIST_ENTRY *cur, *temp;
|
||||
|
||||
#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
|
||||
|
||||
|
@ -222,6 +233,18 @@ rl_do_undo ()
|
|||
|
||||
release = rl_undo_list;
|
||||
rl_undo_list = rl_undo_list->next;
|
||||
|
||||
/* If we are editing a history entry, make sure the change is replicated
|
||||
in the history entry's line */
|
||||
cur = current_history ();
|
||||
if (cur && cur->data && (UNDO_LIST *)cur->data == release)
|
||||
{
|
||||
temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
|
||||
xfree (temp->line);
|
||||
FREE (temp->timestamp);
|
||||
xfree (temp);
|
||||
}
|
||||
|
||||
replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
|
||||
|
||||
xfree (release);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* util.c -- readline utility functions */
|
||||
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2012 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.
|
||||
|
@ -108,7 +108,11 @@ _rl_abort_internal ()
|
|||
_rl_pop_executing_macro ();
|
||||
|
||||
rl_last_func = (rl_command_func_t *)NULL;
|
||||
#if defined (HAVE_POSIX_SIGSETJMP)
|
||||
siglongjmp (_rl_top_level, 1);
|
||||
#else
|
||||
longjmp (_rl_top_level, 1);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -369,11 +373,13 @@ _rl_strpbrk (string1, string2)
|
|||
doesn't matter (strncasecmp). */
|
||||
int
|
||||
_rl_strnicmp (string1, string2, count)
|
||||
char *string1, *string2;
|
||||
const char *string1;
|
||||
const char *string2;
|
||||
int count;
|
||||
{
|
||||
register char *s1, *s2;
|
||||
int d;
|
||||
register const char *s1;
|
||||
register const char *s2;
|
||||
register int d;
|
||||
|
||||
if (count <= 0 || (string1 == string2))
|
||||
return 0;
|
||||
|
@ -389,7 +395,7 @@ _rl_strnicmp (string1, string2, count)
|
|||
break;
|
||||
s2++;
|
||||
}
|
||||
while (--count != 0)
|
||||
while (--count != 0);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -397,10 +403,12 @@ _rl_strnicmp (string1, string2, count)
|
|||
/* strcmp (), but caseless (strcasecmp). */
|
||||
int
|
||||
_rl_stricmp (string1, string2)
|
||||
char *string1, *string2;
|
||||
const char *string1;
|
||||
const char *string2;
|
||||
{
|
||||
register char *s1, *s2;
|
||||
int d;
|
||||
register const char *s1;
|
||||
register const char *s2;
|
||||
register int d;
|
||||
|
||||
s1 = string1;
|
||||
s2 = string2;
|
||||
|
@ -507,7 +515,7 @@ _rl_tropen ()
|
|||
|
||||
if (_rl_tracefp)
|
||||
fclose (_rl_tracefp);
|
||||
sprintf (fnbuf, "/var/tmp/rltrace.%ld", getpid());
|
||||
sprintf (fnbuf, "/var/tmp/rltrace.%ld", (long)getpid());
|
||||
unlink(fnbuf);
|
||||
_rl_tracefp = fopen (fnbuf, "w+");
|
||||
return _rl_tracefp != 0;
|
||||
|
@ -523,4 +531,61 @@ _rl_trclose ()
|
|||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
_rl_settracefp (fp)
|
||||
FILE *fp;
|
||||
{
|
||||
_rl_tracefp = fp;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if HAVE_DECL_AUDIT_USER_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT)
|
||||
#include <sys/socket.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/netlink.h>
|
||||
|
||||
/* Report STRING to the audit system. */
|
||||
void
|
||||
_rl_audit_tty (string)
|
||||
char *string;
|
||||
{
|
||||
struct sockaddr_nl addr;
|
||||
struct msghdr msg;
|
||||
struct nlmsghdr nlm;
|
||||
struct iovec iov[2];
|
||||
size_t size;
|
||||
int fd;
|
||||
|
||||
fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
|
||||
if (fd < 0)
|
||||
return;
|
||||
size = strlen (string) + 1;
|
||||
|
||||
nlm.nlmsg_len = NLMSG_LENGTH (size);
|
||||
nlm.nlmsg_type = AUDIT_USER_TTY;
|
||||
nlm.nlmsg_flags = NLM_F_REQUEST;
|
||||
nlm.nlmsg_seq = 0;
|
||||
nlm.nlmsg_pid = 0;
|
||||
|
||||
iov[0].iov_base = &nlm;
|
||||
iov[0].iov_len = sizeof (nlm);
|
||||
iov[1].iov_base = string;
|
||||
iov[1].iov_len = size;
|
||||
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_pid = 0;
|
||||
addr.nl_groups = 0;
|
||||
|
||||
msg.msg_name = &addr;
|
||||
msg.msg_namelen = sizeof (addr);
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 2;
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = 0;
|
||||
|
||||
(void)sendmsg (fd, &msg, 0);
|
||||
close (fd);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -309,7 +309,6 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
|
|||
#endif /* KEYMAP_SIZE > 128 */
|
||||
};
|
||||
|
||||
|
||||
KEYMAP_ENTRY_ARRAY vi_insertion_keymap = {
|
||||
/* The regular control keys come first. */
|
||||
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */
|
||||
|
|
|
@ -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-2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2012 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.
|
||||
|
@ -108,9 +108,13 @@ static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
|
|||
/* Arrays for the saved marks. */
|
||||
static int vi_mark_chars['z' - 'a' + 1];
|
||||
|
||||
static void _rl_vi_replace_insert PARAMS((int));
|
||||
static void _rl_vi_save_replace PARAMS((void));
|
||||
static void _rl_vi_stuff_insert PARAMS((int));
|
||||
static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
|
||||
|
||||
static void vi_save_insert_buffer PARAMS ((int, int));
|
||||
|
||||
static void _rl_vi_backup PARAMS((void));
|
||||
|
||||
static int _rl_vi_arg_dispatch PARAMS((int));
|
||||
|
@ -188,6 +192,22 @@ _rl_vi_textmod_command (c)
|
|||
return (member (c, vi_textmod));
|
||||
}
|
||||
|
||||
static void
|
||||
_rl_vi_replace_insert (count)
|
||||
int count;
|
||||
{
|
||||
int nchars;
|
||||
|
||||
nchars = strlen (vi_insert_buffer);
|
||||
|
||||
rl_begin_undo_group ();
|
||||
while (count--)
|
||||
/* nchars-1 to compensate for _rl_replace_text using `end+1' in call
|
||||
to rl_delete_text */
|
||||
_rl_replace_text (vi_insert_buffer, rl_point, rl_point+nchars-1);
|
||||
rl_end_undo_group ();
|
||||
}
|
||||
|
||||
static void
|
||||
_rl_vi_stuff_insert (count)
|
||||
int count;
|
||||
|
@ -207,7 +227,7 @@ rl_vi_redo (count, c)
|
|||
{
|
||||
int r;
|
||||
|
||||
if (!rl_explicit_arg)
|
||||
if (rl_explicit_arg == 0)
|
||||
{
|
||||
rl_numeric_arg = _rl_vi_last_repeat;
|
||||
rl_arg_sign = _rl_vi_last_arg_sign;
|
||||
|
@ -224,6 +244,13 @@ rl_vi_redo (count, c)
|
|||
if (rl_point > 0)
|
||||
_rl_vi_backup ();
|
||||
}
|
||||
else if (_rl_vi_last_command == 'R' && vi_insert_buffer && *vi_insert_buffer)
|
||||
{
|
||||
_rl_vi_replace_insert (count);
|
||||
/* And back up point over the last character inserted. */
|
||||
if (rl_point > 0)
|
||||
_rl_vi_backup ();
|
||||
}
|
||||
/* Ditto for redoing an insert with `I', but move to the beginning of the
|
||||
line like the `I' command does. */
|
||||
else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer)
|
||||
|
@ -679,6 +706,8 @@ rl_vi_insertion_mode (count, key)
|
|||
{
|
||||
_rl_keymap = vi_insertion_keymap;
|
||||
_rl_vi_last_key_before_insert = key;
|
||||
if (_rl_show_mode_in_prompt)
|
||||
_rl_reset_prompt ();
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -690,6 +719,43 @@ rl_vi_insert_mode (count, key)
|
|||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
vi_save_insert_buffer (start, len)
|
||||
int start, len;
|
||||
{
|
||||
/* Same code as _rl_vi_save_insert below */
|
||||
if (len >= vi_insert_buffer_size)
|
||||
{
|
||||
vi_insert_buffer_size += (len + 32) - (len % 32);
|
||||
vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
|
||||
}
|
||||
strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
|
||||
vi_insert_buffer[len-1] = '\0';
|
||||
}
|
||||
|
||||
static void
|
||||
_rl_vi_save_replace ()
|
||||
{
|
||||
int len, start, end;
|
||||
UNDO_LIST *up;
|
||||
|
||||
up = rl_undo_list;
|
||||
if (up == 0 || up->what != UNDO_END || vi_replace_count <= 0)
|
||||
{
|
||||
if (vi_insert_buffer_size >= 1)
|
||||
vi_insert_buffer[0] = '\0';
|
||||
return;
|
||||
}
|
||||
/* Let's try it the quick and easy way for now. This should essentially
|
||||
accommodate every UNDO_INSERT and save the inserted text to
|
||||
vi_insert_buffer */
|
||||
end = rl_point;
|
||||
start = end - vi_replace_count + 1;
|
||||
len = vi_replace_count + 1;
|
||||
|
||||
vi_save_insert_buffer (start, len);
|
||||
}
|
||||
|
||||
static void
|
||||
_rl_vi_save_insert (up)
|
||||
UNDO_LIST *up;
|
||||
|
@ -706,13 +772,8 @@ _rl_vi_save_insert (up)
|
|||
start = up->start;
|
||||
end = up->end;
|
||||
len = end - start + 1;
|
||||
if (len >= vi_insert_buffer_size)
|
||||
{
|
||||
vi_insert_buffer_size += (len + 32) - (len % 32);
|
||||
vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
|
||||
}
|
||||
strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
|
||||
vi_insert_buffer[len-1] = '\0';
|
||||
|
||||
vi_save_insert_buffer (start, len);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -728,7 +789,10 @@ _rl_vi_done_inserting ()
|
|||
on absolute indices into the line which may change (though they
|
||||
probably will not). */
|
||||
_rl_vi_doing_insert = 0;
|
||||
_rl_vi_save_insert (rl_undo_list->next);
|
||||
if (_rl_vi_last_key_before_insert == 'R')
|
||||
_rl_vi_save_replace (); /* Half the battle */
|
||||
else
|
||||
_rl_vi_save_insert (rl_undo_list->next);
|
||||
vi_continued_command = 1;
|
||||
}
|
||||
else
|
||||
|
@ -762,6 +826,9 @@ rl_vi_movement_mode (count, key)
|
|||
if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0)
|
||||
rl_free_undo_list ();
|
||||
|
||||
if (_rl_show_mode_in_prompt)
|
||||
_rl_reset_prompt ();
|
||||
|
||||
RL_SETSTATE (RL_STATE_VICMDONCE);
|
||||
return (0);
|
||||
}
|
||||
|
@ -1940,14 +2007,20 @@ rl_vi_replace (count, key)
|
|||
|
||||
vi_replace_count = 0;
|
||||
|
||||
if (!vi_replace_map)
|
||||
if (vi_replace_map == 0)
|
||||
{
|
||||
vi_replace_map = rl_make_bare_keymap ();
|
||||
|
||||
for (i = 0; i < ' '; i++)
|
||||
if (vi_insertion_keymap[i].type == ISFUNC)
|
||||
vi_replace_map[i].function = vi_insertion_keymap[i].function;
|
||||
|
||||
for (i = ' '; i < KEYMAP_SIZE; i++)
|
||||
vi_replace_map[i].function = rl_vi_overstrike;
|
||||
|
||||
vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
|
||||
|
||||
/* Make sure these are what we want. */
|
||||
vi_replace_map[ESC].function = rl_vi_movement_mode;
|
||||
vi_replace_map[RETURN].function = rl_newline;
|
||||
vi_replace_map[NEWLINE].function = rl_newline;
|
||||
|
@ -1960,7 +2033,12 @@ rl_vi_replace (count, key)
|
|||
vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
|
||||
|
||||
}
|
||||
|
||||
rl_vi_start_inserting (key, 1, rl_arg_sign);
|
||||
|
||||
_rl_vi_last_key_before_insert = key;
|
||||
_rl_keymap = vi_replace_map;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.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 dprintf.c input_avail.c mbscasecmp.c fnxform.c \
|
||||
strchrnul.c unicode.c wcswidth.c shmbchar.c
|
||||
strchrnul.c unicode.c wcswidth.c wcsnwidth.c shmbchar.c strdup.c
|
||||
|
||||
# The header files for this library.
|
||||
HSOURCES =
|
||||
|
@ -106,7 +106,8 @@ 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 \
|
||||
input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o ${LIBOBJS}
|
||||
input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o \
|
||||
wcsnwidth.o ${LIBOBJS}
|
||||
|
||||
SUPPORT = Makefile
|
||||
|
||||
|
@ -197,6 +198,7 @@ uconvert.o: uconvert.c
|
|||
ufuncs.o: ufuncs.c
|
||||
vprint.o: vprint.c
|
||||
wcsdup.o: wcsdup.c
|
||||
wcsnwidth.o: wcsnwidth.c
|
||||
wcswidth.o: wcswidth.c
|
||||
mbschr.o: mbschr.c
|
||||
zcatfd.o: zcatfd.c
|
||||
|
@ -269,6 +271,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
|
||||
wcsnwidth.o: ${BUILD_DIR}/config.h
|
||||
wcswidth.o: ${BUILD_DIR}/config.h
|
||||
mbschr.o: ${BUILD_DIR}/config.h
|
||||
zcatfd.o: ${BUILD_DIR}/config.h
|
||||
|
@ -291,7 +294,7 @@ getenv.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
|||
getenv.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
getenv.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
getenv.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
getenv.o: ${BUILD_DIR}/version.h
|
||||
#getenv.o: ${BUILD_DIR}/version.h
|
||||
|
||||
inet_aton.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
inet_aton.o: ${BASHINCDIR}/stdc.h
|
||||
|
@ -303,7 +306,8 @@ itos.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir
|
|||
itos.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
itos.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
itos.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
itos.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
itos.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
#itos.o: ${BUILD_DIR}/version.h
|
||||
|
||||
makepath.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
makepath.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
|
||||
|
@ -312,7 +316,8 @@ makepath.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
|
|||
makepath.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
makepath.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
makepath.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
makepath.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
makepath.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
#makepath.o: ${BUILD_DIR}/version.h
|
||||
|
||||
netconn.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
|
||||
netconn.o: ${topdir}/bashtypes.h
|
||||
|
@ -324,8 +329,9 @@ netopen.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${top
|
|||
netopen.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
netopen.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
netopen.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
netopen.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
#netopen.o: ${BUILD_DIR}/version.h
|
||||
|
||||
oslib.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
|
||||
oslib.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
|
||||
|
@ -334,9 +340,10 @@ oslib.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdi
|
|||
oslib.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
oslib.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
oslib.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
oslib.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
oslib.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
oslib.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
|
||||
oslib.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
|
||||
#oslib.o: ${BUILD_DIR}/version.h
|
||||
|
||||
pathcanon.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
|
||||
pathcanon.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
|
||||
|
@ -345,9 +352,10 @@ pathcanon.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${t
|
|||
pathcanon.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
pathcanon.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
pathcanon.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
pathcanon.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
pathcanon.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
pathcanon.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
|
||||
pathcanon.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
|
||||
#pathcanon.o: ${BUILD_DIR}/version.h
|
||||
|
||||
pathphys.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
|
||||
pathphys.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
|
||||
|
@ -356,9 +364,10 @@ pathphys.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
|
|||
pathphys.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
pathphys.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
pathphys.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
pathphys.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
pathphys.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
|
||||
pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
|
||||
#pathphys.o: ${BUILD_DIR}/version.h
|
||||
|
||||
rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h
|
||||
rename.o: ${BASHINCDIR}/posixstat.h
|
||||
|
@ -377,7 +386,8 @@ eaccess.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${top
|
|||
eaccess.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
eaccess.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
eaccess.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
eaccess.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
eaccess.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
#eaccess.o: ${BUILD_DIR}/version.h
|
||||
|
||||
shquote.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
|
||||
shquote.o: ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
|
||||
|
@ -403,7 +413,8 @@ strerror.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
|
|||
strerror.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
strerror.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
strerror.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
strerror.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
strerror.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
#strerror.o: ${BUILD_DIR}/version.h
|
||||
|
||||
strcasestr.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
|
||||
strcasestr.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
|
||||
|
@ -415,7 +426,8 @@ stringlist.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${
|
|||
stringlist.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
stringlist.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
stringlist.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
stringlist.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
stringlist.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
#stringlist.o: ${BUILD_DIR}/version.h
|
||||
|
||||
stringvec.o: ${topdir}/bashansi.h ${BASHINCDIR}/chartypes.h
|
||||
stringvec.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
|
||||
|
@ -424,7 +436,8 @@ stringvec.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${t
|
|||
stringvec.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
stringvec.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
stringvec.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
#stringvec.o: ${BUILD_DIR}/version.h
|
||||
|
||||
strnlen.o: ${BASHINCDIR}/stdc.h
|
||||
|
||||
|
@ -461,7 +474,8 @@ strtrans.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
|
|||
strtrans.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
strtrans.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
strtrans.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
strtrans.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
strtrans.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
#strtrans.o: ${BUILD_DIR}/version.h
|
||||
|
||||
times.o: ${BASHINCDIR}/systimes.h
|
||||
times.o: ${BASHINCDIR}/posixtime.h
|
||||
|
@ -510,6 +524,9 @@ wcsdup.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
|||
wcsdup.o: ${BASHINCDIR}/stdc.h
|
||||
wcsdup.o: ${topdir}/xmalloc.h
|
||||
|
||||
wcsnwidth.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
wcsnwidth.o: ${BASHINCDIR}/stdc.h
|
||||
|
||||
wcswidth.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
wcswidth.o: ${BASHINCDIR}/stdc.h
|
||||
|
||||
|
|
|
@ -36,8 +36,10 @@
|
|||
#include <ctype.h>
|
||||
#include <xmalloc.h>
|
||||
|
||||
#include <shmbchar.h>
|
||||
#include <shmbutil.h>
|
||||
#include <chartypes.h>
|
||||
#include <typemax.h>
|
||||
|
||||
#include <glob/strmatch.h>
|
||||
|
||||
|
@ -67,6 +69,10 @@
|
|||
|
||||
extern char *substring __P((char *, int, int));
|
||||
|
||||
#ifndef UCHAR_MAX
|
||||
# define UCHAR_MAX TYPE_MAXIMUM(unsigned char)
|
||||
#endif
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
static wchar_t
|
||||
cval (s, i)
|
||||
|
@ -78,7 +84,7 @@ cval (s, i)
|
|||
int l;
|
||||
mbstate_t mps;
|
||||
|
||||
if (MB_CUR_MAX == 1)
|
||||
if (MB_CUR_MAX == 1 || is_basic (s[i]))
|
||||
return ((wchar_t)s[i]);
|
||||
l = strlen (s);
|
||||
if (i >= (l - 1))
|
||||
|
@ -140,8 +146,10 @@ sh_modcase (string, pat, flags)
|
|||
if (iswalnum (wc) == 0)
|
||||
{
|
||||
inword = 0;
|
||||
#if 0
|
||||
ADVANCE_CHAR (ret, end, start);
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pat)
|
||||
|
@ -202,8 +210,11 @@ sh_modcase (string, pat, flags)
|
|||
else
|
||||
nop = flags;
|
||||
|
||||
if (MB_CUR_MAX == 1 || isascii (wc))
|
||||
/* Need to check UCHAR_MAX since wc may have already been converted to a
|
||||
wide character by cval() */
|
||||
if (MB_CUR_MAX == 1 || (wc <= UCHAR_MAX && is_basic ((int)wc)))
|
||||
{
|
||||
singlebyte:
|
||||
switch (nop)
|
||||
{
|
||||
default:
|
||||
|
@ -220,15 +231,18 @@ sh_modcase (string, pat, flags)
|
|||
{
|
||||
m = mbrtowc (&wc, string + start, end - start, &state);
|
||||
if (MB_INVALIDCH (m))
|
||||
wc = (wchar_t)string[start];
|
||||
{
|
||||
wc = (unsigned char)string[start];
|
||||
goto singlebyte;
|
||||
}
|
||||
else if (MB_NULLWCH (m))
|
||||
wc = L'\0';
|
||||
switch (nop)
|
||||
{
|
||||
default:
|
||||
case CASE_NOOP: nwc = wc; break;
|
||||
case CASE_UPPER: nwc = TOUPPER (wc); break;
|
||||
case CASE_LOWER: nwc = TOLOWER (wc); break;
|
||||
case CASE_UPPER: nwc = _to_wupper (wc); break;
|
||||
case CASE_LOWER: nwc = _to_wlower (wc); break;
|
||||
case CASE_TOGGLEALL:
|
||||
case CASE_TOGGLE: nwc = TOGGLE (wc); break;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <bashtypes.h>
|
||||
#include <sys/param.h>
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
|
|
|
@ -205,14 +205,16 @@ sh_eaccess (path, mode)
|
|||
if (path_is_devfd (path))
|
||||
return (sh_stataccess (path, mode));
|
||||
|
||||
#if defined (HAVE_FACCESSAT) && defined (AT_EACCESS)
|
||||
return (faccessat (AT_FDCWD, path, mode, AT_EACCESS));
|
||||
#elif defined (HAVE_EACCESS) /* FreeBSD */
|
||||
#if (defined (HAVE_FACCESSAT) && defined (AT_EACCESS)) || defined (HAVE_EACCESS)
|
||||
# if defined (HAVE_FACCESSAT) && defined (AT_EACCESS)
|
||||
ret = faccessat (AT_FDCWD, path, mode, AT_EACCESS);
|
||||
# else /* HAVE_EACCESS */ /* FreeBSD */
|
||||
ret = eaccess (path, mode); /* XXX -- not always correct for X_OK */
|
||||
# if defined (__FreeBSD__)
|
||||
# endif /* HAVE_EACCESS */
|
||||
# if defined (__FreeBSD__) || defined (SOLARIS)
|
||||
if (ret == 0 && current_user.euid == 0 && mode == X_OK)
|
||||
return (sh_stataccess (path, mode));
|
||||
# endif
|
||||
# endif /* __FreeBSD__ || SOLARIS */
|
||||
return ret;
|
||||
#elif defined (EFF_ONLY_OK) /* SVR4(?), SVR4.2 */
|
||||
return access (path, mode|EFF_ONLY_OK);
|
||||
|
@ -233,7 +235,6 @@ sh_eaccess (path, mode)
|
|||
return (sh_stataccess (path, mode));
|
||||
#endif
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
return (sh_stataccess (path, mode));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* fmtulong.c -- Convert unsigned long int to string. */
|
||||
|
||||
/* Copyright (C) 1998-2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1998-2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -98,8 +98,9 @@ fmtulong (ui, base, buf, len, flags)
|
|||
if (base < 2 || base > 64)
|
||||
{
|
||||
#if 1
|
||||
/* XXX - truncation possible with long translation */
|
||||
strncpy (buf, _("invalid base"), len - 1);
|
||||
buf[len] = '\0';
|
||||
buf[len-1] = '\0';
|
||||
errno = EINVAL;
|
||||
return (p = buf);
|
||||
#else
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
|
||||
#include <bashansi.h>
|
||||
|
||||
#if defined (BROKEN_DIRENT_D_INO)
|
||||
#if !defined (D_FILENO_AVAILABLE)
|
||||
# include "command.h"
|
||||
# include "general.h"
|
||||
# include "externs.h"
|
||||
|
@ -71,7 +71,7 @@ extern int errno;
|
|||
/* If the d_fileno member of a struct dirent doesn't return anything useful,
|
||||
we need to check inode number equivalence the hard way. Return 1 if
|
||||
the inode corresponding to PATH/DIR is identical to THISINO. */
|
||||
#if defined (BROKEN_DIRENT_D_INO)
|
||||
#if !defined (D_FILENO_AVAILABLE)
|
||||
static int
|
||||
_path_checkino (dotp, name, thisino)
|
||||
char *dotp;
|
||||
|
@ -206,7 +206,7 @@ getcwd (buf, size)
|
|||
(d->d_name[1] == '\0' ||
|
||||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
|
||||
continue;
|
||||
#if !defined (BROKEN_DIRENT_D_INO)
|
||||
#if defined (D_FILENO_AVAILABLE)
|
||||
if (mount_point || d->d_fileno == thisino)
|
||||
#else
|
||||
if (mount_point || _path_checkino (dotp, d->d_name, thisino))
|
||||
|
|
|
@ -67,7 +67,9 @@ static char rcsid[] = "$Id: inet_addr.c,v 1.5 1996/08/14 03:48:37 drepper Exp $"
|
|||
#if !defined (HAVE_INET_ATON) && defined (HAVE_NETWORK) && defined (HAVE_NETINET_IN_H) && defined (HAVE_ARPA_INET_H)
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
|
|
@ -50,6 +50,18 @@ itos (i)
|
|||
return (savestring (p));
|
||||
}
|
||||
|
||||
/* Integer to string conversion. This conses the string using strdup;
|
||||
caller should free it and be prepared to deal with NULL return. */
|
||||
char *
|
||||
mitos (i)
|
||||
intmax_t i;
|
||||
{
|
||||
char *p, lbuf[INT_STRLEN_BOUND(intmax_t) + 1];
|
||||
|
||||
p = fmtumax (i, 10, lbuf, sizeof(lbuf), 0);
|
||||
return (strdup (p));
|
||||
}
|
||||
|
||||
char *
|
||||
uinttostr (i, buf, len)
|
||||
uintmax_t i;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <posixdir.h>
|
||||
#include <bashansi.h>
|
||||
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ sh_makepath (path, dir, flags)
|
|||
MAKEDOT();
|
||||
}
|
||||
else if ((flags & MP_IGNDOT) && path[0] == '.' && (path[1] == '\0' ||
|
||||
path[1] == '/' && path[2] == '\0'))
|
||||
(path[1] == '/' && path[2] == '\0')))
|
||||
{
|
||||
xpath = nullpath;
|
||||
pathlen = 0;
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include "bashansi.h"
|
||||
#include "shmbutil.h"
|
||||
|
||||
extern int locale_mb_cur_max;
|
||||
|
||||
#undef mbschr
|
||||
|
||||
/* In some locales, the non-first byte of some multibyte characters have
|
||||
|
@ -51,7 +53,7 @@ mbschr (s, c)
|
|||
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)
|
||||
if ((unsigned char)c >= '0' && locale_mb_cur_max > 1)
|
||||
{
|
||||
pos = (char *)s;
|
||||
memset (&state, '\0', sizeof(mbstate_t));
|
||||
|
@ -59,9 +61,14 @@ mbschr (s, c)
|
|||
|
||||
while (strlength > 0)
|
||||
{
|
||||
mblength = mbrlen (pos, strlength, &state);
|
||||
if (mblength == (size_t)-2 || mblength == (size_t)-1 || mblength == (size_t)0)
|
||||
if (is_basic (*pos))
|
||||
mblength = 1;
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -41,8 +41,6 @@
|
|||
|
||||
#ifndef VMS
|
||||
#include <sys/types.h> /* Some systems define `time_t' here. */
|
||||
#else
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <bashtypes.h>
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
|
@ -124,7 +124,7 @@ dup2 (fd1, fd2)
|
|||
/*
|
||||
* Return the total number of available file descriptors.
|
||||
*
|
||||
* On some systems, like 4.2BSD and its descendents, there is a system call
|
||||
* On some systems, like 4.2BSD and its descendants, there is a system call
|
||||
* that returns the size of the descriptor table: getdtablesize(). There are
|
||||
* lots of ways to emulate this on non-BSD systems.
|
||||
*
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <bashtypes.h>
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#include <posixstat.h>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <bashtypes.h>
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#include <posixstat.h>
|
||||
|
@ -269,7 +269,7 @@ sh_realpath (pathname, resolved)
|
|||
wd = get_working_directory ("sh_realpath");
|
||||
if (wd == 0)
|
||||
return ((char *)NULL);
|
||||
tdir = sh_makepath ((char *)pathname, wd, 0);
|
||||
tdir = sh_makepath (wd, (char *)pathname, 0);
|
||||
free (wd);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2001, 2006, 2009, 2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2001, 2006, 2009, 2010, 2012 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
|
||||
|
@ -89,4 +89,25 @@ mbsmbchar (s)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sh_mbsnlen(src, srclen, maxlen)
|
||||
const char *src;
|
||||
size_t srclen;
|
||||
int maxlen;
|
||||
{
|
||||
int count;
|
||||
int sind;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
for (sind = count = 0; src[sind]; )
|
||||
{
|
||||
count++; /* number of multibyte characters */
|
||||
ADVANCE_CHAR (src, srclen, sind);
|
||||
if (sind > maxlen)
|
||||
break;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
|
109
lib/sh/shquote.c
109
lib/sh/shquote.c
|
@ -32,6 +32,50 @@
|
|||
#include "syntax.h"
|
||||
#include <xmalloc.h>
|
||||
|
||||
/* Default set of characters that should be backslash-quoted in strings */
|
||||
static const char bstab[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, /* TAB, NL */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
1, 1, 1, 0, 1, 0, 1, 1, /* SPACE, !, DQUOTE, DOL, AMP, SQUOTE */
|
||||
1, 1, 1, 0, 1, 0, 0, 0, /* LPAR, RPAR, STAR, COMMA */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 0, 1, 1, /* SEMI, LESSTHAN, GREATERTHAN, QUEST */
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 1, 1, 0, /* LBRACK, BS, RBRACK, CARAT */
|
||||
|
||||
1, 0, 0, 0, 0, 0, 0, 0, /* BACKQ */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 1, 0, 0, /* LBRACE, BAR, RBRACE */
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Functions for quoting strings to be re-read as input */
|
||||
|
@ -50,6 +94,15 @@ sh_single_quote (string)
|
|||
|
||||
result = (char *)xmalloc (3 + (4 * strlen (string)));
|
||||
r = result;
|
||||
|
||||
if (string[0] == '\'' && string[1] == 0)
|
||||
{
|
||||
*r++ = '\\';
|
||||
*r++ = '\'';
|
||||
*r++ = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
*r++ = '\'';
|
||||
|
||||
for (s = string; s && (c = *s); s++)
|
||||
|
@ -163,53 +216,33 @@ sh_un_double_quote (string)
|
|||
way to protect the CTLESC and CTLNUL characters. As I write this,
|
||||
the current callers will never cause the string to be expanded without
|
||||
going through the shell parser, which will protect the internal
|
||||
quoting characters. */
|
||||
quoting characters. TABLE, if set, points to a map of the ascii code
|
||||
set with char needing to be backslash-quoted if table[char]==1. FLAGS,
|
||||
if 1, causes tildes to be quoted as well. */
|
||||
|
||||
char *
|
||||
sh_backslash_quote (string)
|
||||
sh_backslash_quote (string, table, flags)
|
||||
char *string;
|
||||
char *table;
|
||||
int flags;
|
||||
{
|
||||
int c;
|
||||
char *result, *r, *s;
|
||||
char *result, *r, *s, *backslash_table;
|
||||
|
||||
result = (char *)xmalloc (2 * strlen (string) + 1);
|
||||
|
||||
backslash_table = table ? table : (char *)bstab;
|
||||
for (r = result, s = string; s && (c = *s); s++)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case ' ': case '\t': case '\n': /* IFS white space */
|
||||
case '\'': case '"': case '\\': /* quoting chars */
|
||||
case '|': case '&': case ';': /* shell metacharacters */
|
||||
case '(': case ')': case '<': case '>':
|
||||
case '!': case '{': case '}': /* reserved words */
|
||||
case '*': case '[': case '?': case ']': /* globbing chars */
|
||||
case '^':
|
||||
case '$': case '`': /* expansion chars */
|
||||
case ',': /* brace expansion */
|
||||
*r++ = '\\';
|
||||
*r++ = c;
|
||||
break;
|
||||
#if 0
|
||||
case '~': /* tilde expansion */
|
||||
if (s == string || s[-1] == '=' || s[-1] == ':')
|
||||
*r++ = '\\';
|
||||
*r++ = c;
|
||||
break;
|
||||
|
||||
case CTLESC: case CTLNUL: /* internal quoting characters */
|
||||
*r++ = CTLESC; /* could be '\\'? */
|
||||
*r++ = c;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case '#': /* comment char */
|
||||
if (s == string)
|
||||
*r++ = '\\';
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
*r++ = c;
|
||||
break;
|
||||
}
|
||||
if (backslash_table[c] == 1)
|
||||
*r++ = '\\';
|
||||
else if (c == '#' && s == string) /* comment char */
|
||||
*r++ = '\\';
|
||||
else if ((flags&1) && c == '~' && (s == string || s[-1] == ':' || s[-1] == '='))
|
||||
/* Tildes are special at the start of a word or after a `:' or `='
|
||||
(technically unquoted, but it doesn't make a difference in practice) */
|
||||
*r++ = '\\';
|
||||
*r++ = c;
|
||||
}
|
||||
|
||||
*r = '\0';
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
Unix snprintf implementation.
|
||||
derived from inetutils/libinetutils/snprintf.c Version 1.1
|
||||
|
||||
Copyright (C) 2001,2006,2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001,2006,2010,2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Revision History:
|
||||
Original (pre-bash) Revision History:
|
||||
|
||||
1.1:
|
||||
* added changes from Miles Bader
|
||||
|
@ -50,7 +50,6 @@
|
|||
* Currently doesn't handle (and bash/readline doesn't use):
|
||||
* * *M$ width, precision specifications
|
||||
* * %N$ numbered argument conversions
|
||||
* * inf, nan floating values imperfect (if isinf(), isnan() not in libc)
|
||||
* * support for `F' is imperfect with ldfallback(), since underlying
|
||||
* printf may not handle it -- should ideally have another autoconf test
|
||||
*/
|
||||
|
@ -303,11 +302,30 @@ static void dfallback __P((struct DATA *, const char *, const char *, double));
|
|||
|
||||
static char *groupnum __P((char *));
|
||||
|
||||
#ifndef HAVE_ISINF_IN_LIBC
|
||||
static int isinf __P((double));
|
||||
#if defined (HAVE_LONG_DOUBLE)
|
||||
# define LONGDOUBLE long double
|
||||
#else
|
||||
# define LONGDOUBLE double
|
||||
#endif
|
||||
#ifndef HAVE_ISNAN_IN_LIBC
|
||||
static int isnan __P((double));
|
||||
|
||||
#ifndef isnan
|
||||
static inline int isnan_f (float x) { return x != x; }
|
||||
static inline int isnan_d (double x) { return x != x; }
|
||||
static inline int isnan_ld (LONGDOUBLE x) { return x != x; }
|
||||
# define isnan(x) \
|
||||
(sizeof (x) == sizeof (LONGDOUBLE) ? isnan_ld (x) \
|
||||
: sizeof (x) == sizeof (double) ? isnan_d (x) \
|
||||
: isnan_f (x))
|
||||
#endif
|
||||
|
||||
#ifndef isinf
|
||||
static inline int isinf_f (float x) { return !isnan (x) && isnan (x - x); }
|
||||
static inline int isinf_d (double x) { return !isnan (x) && isnan (x - x); }
|
||||
static inline int isinf_ld (LONGDOUBLE x) { return !isnan (x) && isnan (x - x); }
|
||||
# define isinf(x) \
|
||||
(sizeof (x) == sizeof (LONGDOUBLE) ? isinf_ld (x) \
|
||||
: sizeof (x) == sizeof (double) ? isinf_d (x) \
|
||||
: isinf_f (x))
|
||||
#endif
|
||||
|
||||
#ifdef DRIVER
|
||||
|
@ -371,7 +389,7 @@ static void xfree __P((void *));
|
|||
while (0)
|
||||
|
||||
#define PUT_PLUS(d, p, zero) \
|
||||
if ((d) > zero && (p)->justify == RIGHT) \
|
||||
if (((p)->flags & PF_PLUS) && (d) > zero) \
|
||||
PUT_CHAR('+', p)
|
||||
|
||||
#define PUT_SPACE(d, p, zero) \
|
||||
|
@ -431,9 +449,9 @@ static void xfree __P((void *));
|
|||
if (lv) \
|
||||
{ \
|
||||
if (lv->decimal_point && lv->decimal_point[0]) \
|
||||
(d) = lv->decimal_point[0]; \
|
||||
(d) = lv->decimal_point[0]; \
|
||||
if (lv->thousands_sep && lv->thousands_sep[0]) \
|
||||
(t) = lv->thousands_sep[0]; \
|
||||
(t) = lv->thousands_sep[0]; \
|
||||
(g) = lv->grouping ? lv->grouping : ""; \
|
||||
if (*(g) == '\0' || *(g) == CHAR_MAX || (t) == -1) (g) = 0; \
|
||||
} \
|
||||
|
@ -574,7 +592,7 @@ integral(real, ip)
|
|||
/*
|
||||
* return an ascii representation of the integral part of the number
|
||||
* and set fract to be an ascii representation of the fraction part
|
||||
* the container for the fraction and the integral part or staticly
|
||||
* the container for the fraction and the integral part or statically
|
||||
* declare with fix size
|
||||
*/
|
||||
static char *
|
||||
|
@ -586,10 +604,9 @@ numtoa(number, base, precision, fract)
|
|||
register int i, j;
|
||||
double ip, fp; /* integer and fraction part */
|
||||
double fraction;
|
||||
int digits = MAX_INT - 1;
|
||||
int digits, sign;
|
||||
static char integral_part[MAX_INT];
|
||||
static char fraction_part[MAX_FRACT];
|
||||
double sign;
|
||||
int ch;
|
||||
|
||||
/* taking care of the obvious case: 0.0 */
|
||||
|
@ -607,8 +624,12 @@ numtoa(number, base, precision, fract)
|
|||
return integral_part;
|
||||
}
|
||||
|
||||
/* -0 is tricky */
|
||||
sign = (number == -0.) ? '-' : ((number < 0.) ? '-' : '+');
|
||||
digits = MAX_INT - 1;
|
||||
|
||||
/* for negative numbers */
|
||||
if ((sign = number) < 0.)
|
||||
if (sign == '-')
|
||||
{
|
||||
number = -number;
|
||||
digits--; /* sign consume one digit */
|
||||
|
@ -643,7 +664,7 @@ numtoa(number, base, precision, fract)
|
|||
integral_part[i] = '9';
|
||||
|
||||
/* put the sign ? */
|
||||
if (sign < 0.)
|
||||
if (sign == '-')
|
||||
integral_part[i++] = '-';
|
||||
|
||||
integral_part[i] = '\0';
|
||||
|
@ -682,9 +703,13 @@ number(p, d, base)
|
|||
long sd;
|
||||
int flags;
|
||||
|
||||
/* An explicit precision turns off the zero-padding flag. */
|
||||
/* An explicit precision turns off the zero-padding flag and sets the
|
||||
pad character back to space. */
|
||||
if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
|
||||
p->flags &= ~PF_ZEROPAD;
|
||||
{
|
||||
p->flags &= ~PF_ZEROPAD;
|
||||
p->pad = ' ';
|
||||
}
|
||||
|
||||
sd = d; /* signed for ' ' padding in base 10 */
|
||||
flags = 0;
|
||||
|
@ -698,10 +723,11 @@ number(p, d, base)
|
|||
{
|
||||
GETLOCALEDATA(decpoint, thoussep, grouping);
|
||||
if (grouping && (t = groupnum (tmp)))
|
||||
tmp = t;
|
||||
tmp = t;
|
||||
}
|
||||
|
||||
p->width -= strlen(tmp);
|
||||
/* need to add one for any `+', but we only add one in base 10 */
|
||||
p->width -= strlen(tmp) + (base == 10 && d > 0 && (p->flags & PF_PLUS));
|
||||
PAD_RIGHT(p);
|
||||
|
||||
if ((p->flags & PF_DOT) && p->precision > 0)
|
||||
|
@ -753,9 +779,13 @@ lnumber(p, d, base)
|
|||
long long sd;
|
||||
int flags;
|
||||
|
||||
/* An explicit precision turns off the zero-padding flag. */
|
||||
/* An explicit precision turns off the zero-padding flag and sets the
|
||||
pad character back to space. */
|
||||
if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
|
||||
p->flags &= ~PF_ZEROPAD;
|
||||
{
|
||||
p->flags &= ~PF_ZEROPAD;
|
||||
p->pad = ' ';
|
||||
}
|
||||
|
||||
sd = d; /* signed for ' ' padding in base 10 */
|
||||
flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
|
||||
|
@ -768,10 +798,11 @@ lnumber(p, d, base)
|
|||
{
|
||||
GETLOCALEDATA(decpoint, thoussep, grouping);
|
||||
if (grouping && (t = groupnum (tmp)))
|
||||
tmp = t;
|
||||
tmp = t;
|
||||
}
|
||||
|
||||
p->width -= strlen(tmp);
|
||||
/* need to add one for any `+', but we only add one in base 10 */
|
||||
p->width -= strlen(tmp) + (base == 10 && d > 0 && (p->flags & PF_PLUS));
|
||||
PAD_RIGHT(p);
|
||||
|
||||
if ((p->flags & PF_DOT) && p->precision > 0)
|
||||
|
@ -875,11 +906,11 @@ wstrings(p, tmp)
|
|||
{
|
||||
len = wcsrtombs (NULL, &ws, 0, &mbs);
|
||||
if (len != (size_t)-1)
|
||||
{
|
||||
{
|
||||
memset (&mbs, '\0', sizeof (mbstate_t));
|
||||
os = (char *)xmalloc (len + 1);
|
||||
(void)wcsrtombs (os, &ws, len + 1, &mbs);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (len == (size_t)-1)
|
||||
{
|
||||
|
@ -919,32 +950,6 @@ wchars (p, wc)
|
|||
|
||||
#ifdef FLOATING_POINT
|
||||
|
||||
#ifndef HAVE_ISINF_IN_LIBC
|
||||
/* Half-assed versions, since we don't want to link with libm. */
|
||||
static int
|
||||
isinf(d)
|
||||
double d;
|
||||
{
|
||||
#ifdef DBL_MAX
|
||||
if (d < DBL_MIN)
|
||||
return -1;
|
||||
else if (d > DBL_MAX)
|
||||
return 1;
|
||||
else
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ISNAN_IN_LIBC
|
||||
static int
|
||||
isnan(d)
|
||||
double d;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check for [+-]infinity and NaN. If MODE == 1, we check for Infinity, else
|
||||
(mode == 2) we check for NaN. This does the necessary printing. Returns
|
||||
1 if Inf or Nan, 0 if not. */
|
||||
|
@ -1002,19 +1007,35 @@ floating(p, d)
|
|||
{
|
||||
/* smash the trailing zeros unless altform */
|
||||
for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
|
||||
tmp2[i] = '\0';
|
||||
tmp2[i] = '\0';
|
||||
if (tmp2[0] == '\0')
|
||||
p->precision = 0;
|
||||
}
|
||||
|
||||
/* calculate the padding. 1 for the dot */
|
||||
p->width = p->width -
|
||||
/* XXX - should this be d>0. && (p->flags & PF_PLUS) ? */
|
||||
#if 0
|
||||
((d > 0. && p->justify == RIGHT) ? 1:0) -
|
||||
#else
|
||||
((d > 0. && (p->flags & PF_PLUS)) ? 1:0) -
|
||||
#endif
|
||||
((p->flags & PF_SPACE) ? 1:0) -
|
||||
strlen(tmp) - p->precision -
|
||||
((p->precision != 0 || (p->flags & PF_ALTFORM)) ? 1 : 0); /* radix char */
|
||||
PAD_RIGHT(p);
|
||||
PUT_PLUS(d, p, 0.);
|
||||
|
||||
if (p->pad == ' ')
|
||||
{
|
||||
PAD_RIGHT(p);
|
||||
PUT_PLUS(d, p, 0.);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*tmp == '-')
|
||||
PUT_CHAR(*tmp++, p);
|
||||
PUT_PLUS(d, p, 0.);
|
||||
PAD_RIGHT(p);
|
||||
}
|
||||
PUT_SPACE(d, p, 0.);
|
||||
|
||||
while (*tmp)
|
||||
|
@ -1058,14 +1079,30 @@ exponent(p, d)
|
|||
tmp = dtoa(d, p->precision, &tmp2);
|
||||
|
||||
/* 1 for unit, 1 for the '.', 1 for 'e|E',
|
||||
* 1 for '+|-', 2 for 'exp' */
|
||||
* 1 for '+|-', 2 for 'exp' (but no `.' if precision == 0 */
|
||||
/* calculate how much padding need */
|
||||
p->width = p->width -
|
||||
/* XXX - should this be d>0. && (p->flags & PF_PLUS) ? */
|
||||
#if 0
|
||||
((d > 0. && p->justify == RIGHT) ? 1:0) -
|
||||
((p->flags & PF_SPACE) ? 1:0) - p->precision - 6;
|
||||
#else
|
||||
((d > 0. && (p->flags & PF_PLUS)) ? 1:0) -
|
||||
#endif
|
||||
(p->precision != 0 || (p->flags & PF_ALTFORM)) -
|
||||
((p->flags & PF_SPACE) ? 1:0) - p->precision - 5;
|
||||
|
||||
PAD_RIGHT(p);
|
||||
PUT_PLUS(d, p, 0.);
|
||||
if (p->pad == ' ')
|
||||
{
|
||||
PAD_RIGHT(p);
|
||||
PUT_PLUS(d, p, 0.);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*tmp == '-')
|
||||
PUT_CHAR(*tmp++, p);
|
||||
PUT_PLUS(d, p, 0.);
|
||||
PAD_RIGHT(p);
|
||||
}
|
||||
PUT_SPACE(d, p, 0.);
|
||||
|
||||
while (*tmp)
|
||||
|
@ -1163,7 +1200,7 @@ groupnum (s)
|
|||
else if (*g == CHAR_MAX)
|
||||
{
|
||||
do
|
||||
*--re = *--se;
|
||||
*--re = *--se;
|
||||
while (se > s);
|
||||
break;
|
||||
}
|
||||
|
@ -1295,10 +1332,6 @@ vsnprintf_internal(data, string, length, format, args)
|
|||
case '#':
|
||||
data->flags |= PF_ALTFORM;
|
||||
continue;
|
||||
case '0':
|
||||
data->flags |= PF_ZEROPAD;
|
||||
data->pad = '0';
|
||||
continue;
|
||||
case '*':
|
||||
if (data->flags & PF_DOT)
|
||||
data->flags |= PF_STAR_P;
|
||||
|
@ -1322,13 +1355,25 @@ vsnprintf_internal(data, string, length, format, args)
|
|||
if ((data->flags & PF_DOT) == 0)
|
||||
{
|
||||
data->flags |= PF_PLUS;
|
||||
data->justify = RIGHT;
|
||||
if ((data->flags & PF_LADJUST) == 0)
|
||||
data->justify = RIGHT;
|
||||
}
|
||||
continue;
|
||||
case '\'':
|
||||
data->flags |= PF_THOUSANDS;
|
||||
continue;
|
||||
|
||||
case '0':
|
||||
/* If we're not specifying precision (in which case we've seen
|
||||
a `.') and we're not performing left-adjustment (in which
|
||||
case the `0' is ignored), a `0' is taken as the zero-padding
|
||||
flag. */
|
||||
if ((data->flags & (PF_DOT|PF_LADJUST)) == 0)
|
||||
{
|
||||
data->flags |= PF_ZEROPAD;
|
||||
data->pad = '0';
|
||||
continue;
|
||||
}
|
||||
case '1': case '2': case '3':
|
||||
case '4': case '5': case '6':
|
||||
case '7': case '8': case '9':
|
||||
|
@ -1410,8 +1455,9 @@ conv_break:
|
|||
else
|
||||
{
|
||||
/* reduce precision by 1 because of leading digit before
|
||||
decimal point in e format. */
|
||||
data->precision--;
|
||||
decimal point in e format, unless specified as 0. */
|
||||
if (data->precision > 0)
|
||||
data->precision--;
|
||||
exponent(data, d);
|
||||
}
|
||||
state = 0;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <bashtypes.h>
|
||||
#include <posixdir.h>
|
||||
#include <posixstat.h>
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Searching in a string.
|
||||
Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012 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
|
||||
|
@ -15,130 +15,21 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.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;
|
||||
char c;
|
||||
register char *s1;
|
||||
|
||||
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;
|
||||
for (c = c_in, s1 = (char *)s; s1 && *s1 && *s1 != c; s1++)
|
||||
;
|
||||
return (s1);
|
||||
}
|
||||
|
|
42
lib/sh/strdup.c
Normal file
42
lib/sh/strdup.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* strdup - return a copy of a string in newly-allocated memory. */
|
||||
|
||||
/* Copyright (C) 2013 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>
|
||||
|
||||
/* Get specification. */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Duplicate S, returning an identical malloc'd string. */
|
||||
char *
|
||||
strdup (s)
|
||||
const char *s;
|
||||
{
|
||||
size_t len;
|
||||
void *new;
|
||||
|
||||
len = strlen (s) + 1;
|
||||
if ((new = malloc (len)) == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy (new, s, len);
|
||||
return ((char *)new);
|
||||
}
|
|
@ -23,7 +23,7 @@
|
|||
#if !defined (HAVE_STRERROR)
|
||||
|
||||
#include <bashtypes.h>
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
* Updated September, 2000
|
||||
* Updated December, 2001
|
||||
* Updated January, 2011
|
||||
* Updated April, 2012
|
||||
*
|
||||
* Fixes from ado@elsie.nci.nih.gov,
|
||||
* February 1991, May 1992
|
||||
|
@ -75,6 +76,7 @@
|
|||
#define VMS_EXT 1 /* include %v for VMS date format */
|
||||
#define HPUX_EXT 1 /* non-conflicting stuff in HP-UX date */
|
||||
#define POSIX_SEMANTICS 1 /* call tzset() if TZ changes */
|
||||
#define POSIX_2008 1 /* flag and fw for C, F, G, Y formats */
|
||||
|
||||
#undef strchr /* avoid AIX weirdness */
|
||||
|
||||
|
@ -96,27 +98,25 @@ static int iso8601wknum(const struct tm *timeptr);
|
|||
|
||||
#define range(low, item, hi) max(low, min(item, hi))
|
||||
|
||||
#if !defined(OS2) && !defined(MSDOS) && defined(HAVE_TZNAME)
|
||||
/* Whew! This stuff is a mess. */
|
||||
#if !defined(OS2) && !defined(MSDOS) && !defined(__CYGWIN__) && defined(HAVE_TZNAME)
|
||||
extern char *tzname[2];
|
||||
extern int daylight;
|
||||
#if defined(SOLARIS) || defined(mips) || defined (M_UNIX)
|
||||
extern long int timezone, altzone;
|
||||
#else
|
||||
# if defined (HPUX)
|
||||
# if defined (HPUX) || defined(__hpux)
|
||||
extern long int timezone;
|
||||
# else
|
||||
# if !defined(__CYGWIN__)
|
||||
extern int timezone, altzone;
|
||||
# endif /* !HPUX */
|
||||
#endif /* !SOLARIS && !mips && !M_UNIX */
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
@ -135,6 +135,34 @@ max(int a, int b)
|
|||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
#ifdef POSIX_2008
|
||||
/* iso_8601_2000_year --- format a year per ISO 8601:2000 as in 1003.1 */
|
||||
|
||||
static void
|
||||
iso_8601_2000_year(char *buf, int year, size_t fw)
|
||||
{
|
||||
int extra;
|
||||
char sign = '\0';
|
||||
|
||||
if (year >= -9999 && year <= 9999) {
|
||||
sprintf(buf, "%0*d", (int) fw, year);
|
||||
return;
|
||||
}
|
||||
|
||||
/* now things get weird */
|
||||
if (year > 9999) {
|
||||
sign = '+';
|
||||
} else {
|
||||
sign = '-';
|
||||
year = -year;
|
||||
}
|
||||
|
||||
extra = year / 10000;
|
||||
year %= 10000;
|
||||
sprintf(buf, "%c_%04d_%d", sign, extra, year);
|
||||
}
|
||||
#endif /* POSIX_2008 */
|
||||
|
||||
/* strftime --- produce formatted time */
|
||||
|
||||
size_t
|
||||
|
@ -155,12 +183,19 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
|
|||
#ifndef HAVE_TM_ZONE
|
||||
#ifndef HAVE_TM_NAME
|
||||
#ifndef HAVE_TZNAME
|
||||
#ifndef __CYGWIN__
|
||||
extern char *timezone();
|
||||
struct timeval tv;
|
||||
struct timezone zone;
|
||||
#endif /* __CYGWIN__ */
|
||||
#endif /* HAVE_TZNAME */
|
||||
#endif /* HAVE_TM_NAME */
|
||||
#endif /* HAVE_TM_ZONE */
|
||||
#ifdef POSIX_2008
|
||||
int pad;
|
||||
size_t fw;
|
||||
char flag;
|
||||
#endif /* POSIX_2008 */
|
||||
|
||||
/* various tables, useful in North America */
|
||||
static const char *days_a[] = {
|
||||
|
@ -234,6 +269,40 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
|
|||
*s++ = *format;
|
||||
continue;
|
||||
}
|
||||
#ifdef POSIX_2008
|
||||
pad = '\0';
|
||||
fw = 0;
|
||||
flag = '\0';
|
||||
switch (*++format) {
|
||||
case '+':
|
||||
flag = '+';
|
||||
/* fall through */
|
||||
case '0':
|
||||
pad = '0';
|
||||
format++;
|
||||
break;
|
||||
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
break;
|
||||
|
||||
default:
|
||||
format--;
|
||||
goto again;
|
||||
}
|
||||
for (; isdigit(*format); format++) {
|
||||
fw = fw * 10 + (*format - '0');
|
||||
}
|
||||
format--;
|
||||
#endif /* POSIX_2008 */
|
||||
|
||||
again:
|
||||
switch (*++format) {
|
||||
case '\0':
|
||||
|
@ -285,8 +354,19 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
|
|||
break;
|
||||
|
||||
case 'C':
|
||||
#ifdef POSIX_2008
|
||||
if (pad != '\0' && fw > 0) {
|
||||
size_t min_fw = (flag ? 3 : 2);
|
||||
|
||||
fw = max(fw, min_fw);
|
||||
sprintf(tbuf, flag
|
||||
? "%+0*ld"
|
||||
: "%0*ld", (int) fw,
|
||||
(timeptr->tm_year + 1900L) / 100);
|
||||
} else
|
||||
#endif /* POSIX_2008 */
|
||||
century:
|
||||
sprintf(tbuf, "%02ld", (timeptr->tm_year + 1900L) / 100);
|
||||
sprintf(tbuf, "%02ld", (timeptr->tm_year + 1900L) / 100);
|
||||
break;
|
||||
|
||||
case 'd': /* day of the month, 01 - 31 */
|
||||
|
@ -307,7 +387,30 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
|
|||
goto again;
|
||||
|
||||
case 'F': /* ISO 8601 date representation */
|
||||
{
|
||||
#ifdef POSIX_2008
|
||||
/*
|
||||
* Field width for %F is for the whole thing.
|
||||
* It must be at least 10.
|
||||
*/
|
||||
char m_d[10];
|
||||
strftime(m_d, sizeof m_d, "-%m-%d", timeptr);
|
||||
size_t min_fw = 10;
|
||||
|
||||
if (pad != '\0' && fw > 0) {
|
||||
fw = max(fw, min_fw);
|
||||
} else {
|
||||
fw = min_fw;
|
||||
}
|
||||
|
||||
fw -= 6; /* -XX-XX at end are invariant */
|
||||
|
||||
iso_8601_2000_year(tbuf, timeptr->tm_year + 1900, fw);
|
||||
strcat(tbuf, m_d);
|
||||
#else
|
||||
strftime(tbuf, sizeof tbuf, "%Y-%m-%d", timeptr);
|
||||
#endif /* POSIX_2008 */
|
||||
}
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
|
@ -329,8 +432,20 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
|
|||
else
|
||||
y = 1900L + timeptr->tm_year;
|
||||
|
||||
if (*format == 'G')
|
||||
sprintf(tbuf, "%ld", y);
|
||||
if (*format == 'G') {
|
||||
#ifdef POSIX_2008
|
||||
if (pad != '\0' && fw > 0) {
|
||||
size_t min_fw = 4;
|
||||
|
||||
fw = max(fw, min_fw);
|
||||
sprintf(tbuf, flag
|
||||
? "%+0*ld"
|
||||
: "%0*ld", (int) fw,
|
||||
y);
|
||||
} else
|
||||
#endif /* POSIX_2008 */
|
||||
sprintf(tbuf, "%ld", y);
|
||||
}
|
||||
else
|
||||
sprintf(tbuf, "%02ld", y % 100);
|
||||
break;
|
||||
|
@ -455,7 +570,17 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
|
|||
break;
|
||||
|
||||
case 'Y': /* year with century */
|
||||
fullyear:
|
||||
#ifdef POSIX_2008
|
||||
if (pad != '\0' && fw > 0) {
|
||||
size_t min_fw = 4;
|
||||
|
||||
fw = max(fw, min_fw);
|
||||
sprintf(tbuf, flag
|
||||
? "%+0*ld"
|
||||
: "%0*ld", (int) fw,
|
||||
1900L + timeptr->tm_year);
|
||||
} else
|
||||
#endif /* POSIX_2008 */
|
||||
sprintf(tbuf, "%ld", 1900L + timeptr->tm_year);
|
||||
break;
|
||||
|
||||
|
@ -496,12 +621,12 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
|
|||
* Systems with tzname[] probably have timezone as
|
||||
* secs west of GMT. Convert to mins east of GMT.
|
||||
*/
|
||||
# ifdef HPUX
|
||||
# if defined(__hpux) || defined (HPUX) || defined(__CYGWIN__)
|
||||
off = -timezone / 60;
|
||||
# else
|
||||
/* ADR: 4 August 2001, fixed this per gazelle@interaccess.com */
|
||||
off = -(daylight ? altzone : timezone) / 60;
|
||||
# endif /* !HPUX */
|
||||
# endif
|
||||
#else /* !HAVE_TZNAME */
|
||||
gettimeofday(& tv, & zone);
|
||||
off = -zone.tz_minuteswest;
|
||||
|
|
|
@ -40,6 +40,14 @@ strvec_create (n)
|
|||
return ((char **)xmalloc ((n) * sizeof (char *)));
|
||||
}
|
||||
|
||||
/* Allocate an array of strings with room for N members. */
|
||||
char **
|
||||
strvec_mcreate (n)
|
||||
int n;
|
||||
{
|
||||
return ((char **)malloc ((n) * sizeof (char *)));
|
||||
}
|
||||
|
||||
char **
|
||||
strvec_resize (array, nsize)
|
||||
char **array;
|
||||
|
@ -48,6 +56,14 @@ strvec_resize (array, nsize)
|
|||
return ((char **)xrealloc (array, nsize * sizeof (char *)));
|
||||
}
|
||||
|
||||
char **
|
||||
strvec_mresize (array, nsize)
|
||||
char **array;
|
||||
int nsize;
|
||||
{
|
||||
return ((char **)realloc (array, nsize * sizeof (char *)));
|
||||
}
|
||||
|
||||
/* Return the length of ARRAY, a NULL terminated array of char *. */
|
||||
int
|
||||
strvec_len (array)
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include <stdc.h>
|
||||
|
||||
/* Find the first ocurrence in S of any character in ACCEPT. */
|
||||
/* Find the first occurrence in S of any character in ACCEPT. */
|
||||
char *
|
||||
strpbrk (s, accept)
|
||||
register const char *s;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* strtrans.c - Translate and untranslate strings with ANSI-C escape sequences. */
|
||||
|
||||
/* Copyright (C) 2000-2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2000-2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -30,6 +30,9 @@
|
|||
|
||||
#include "shell.h"
|
||||
|
||||
#include "shmbchar.h"
|
||||
#include "shmbutil.h"
|
||||
|
||||
#ifdef ESC
|
||||
#undef ESC
|
||||
#endif
|
||||
|
@ -74,7 +77,7 @@ ansicstr (string, len, flags, sawc, rlen)
|
|||
case 'a': c = '\a'; break;
|
||||
case 'v': c = '\v'; break;
|
||||
#else
|
||||
case 'a': c = '\007'; break;
|
||||
case 'a': c = (int) 0x07; break;
|
||||
case 'v': c = (int) 0x0B; break;
|
||||
#endif
|
||||
case 'b': c = '\b'; break;
|
||||
|
@ -144,7 +147,7 @@ ansicstr (string, len, flags, sawc, rlen)
|
|||
*r++ = '\\'; /* c remains unchanged */
|
||||
break;
|
||||
}
|
||||
else if (v <= UCHAR_MAX)
|
||||
else if (v <= 0x7f) /* <= 0x7f translates directly */
|
||||
{
|
||||
c = v;
|
||||
break;
|
||||
|
@ -208,6 +211,11 @@ ansic_quote (str, flags, rlen)
|
|||
char *r, *ret, *s;
|
||||
int l, rsize;
|
||||
unsigned char c;
|
||||
size_t clen;
|
||||
int b;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
wchar_t wc;
|
||||
#endif
|
||||
|
||||
if (str == 0 || *str == 0)
|
||||
return ((char *)0);
|
||||
|
@ -219,10 +227,13 @@ ansic_quote (str, flags, rlen)
|
|||
*r++ = '$';
|
||||
*r++ = '\'';
|
||||
|
||||
for (s = str, l = 0; *s; s++)
|
||||
s = str;
|
||||
|
||||
for (s = str; c = *s; s++)
|
||||
{
|
||||
c = *s;
|
||||
l = 1; /* 1 == add backslash; 0 == no backslash */
|
||||
b = l = 1; /* 1 == add backslash; 0 == no backslash */
|
||||
clen = 1;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case ESC: c = 'E'; break;
|
||||
|
@ -230,7 +241,7 @@ ansic_quote (str, flags, rlen)
|
|||
case '\a': c = 'a'; break;
|
||||
case '\v': c = 'v'; break;
|
||||
#else
|
||||
case '\007': c = 'a'; break;
|
||||
case 0x07: c = 'a'; break;
|
||||
case 0x0b: c = 'v'; break;
|
||||
#endif
|
||||
|
||||
|
@ -243,7 +254,14 @@ ansic_quote (str, flags, rlen)
|
|||
case '\'':
|
||||
break;
|
||||
default:
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
b = is_basic (c);
|
||||
/* XXX - clen comparison to 0 is dicey */
|
||||
if ((b == 0 && ((clen = mbrtowc (&wc, s, MB_CUR_MAX, 0)) < 0 || MB_INVALIDCH (clen) || iswprint (wc) == 0)) ||
|
||||
(b == 1 && ISPRINT (c) == 0))
|
||||
#else
|
||||
if (ISPRINT (c) == 0)
|
||||
#endif
|
||||
{
|
||||
*r++ = '\\';
|
||||
*r++ = TOCHAR ((c >> 6) & 07);
|
||||
|
@ -254,9 +272,20 @@ ansic_quote (str, flags, rlen)
|
|||
l = 0;
|
||||
break;
|
||||
}
|
||||
if (b == 0 && clen == 0)
|
||||
break;
|
||||
|
||||
if (l)
|
||||
*r++ = '\\';
|
||||
*r++ = c;
|
||||
|
||||
if (clen == 1)
|
||||
*r++ = c;
|
||||
else
|
||||
{
|
||||
for (b = 0; b < (int)clen; b++)
|
||||
*r++ = (unsigned char)s[b];
|
||||
s += clen - 1; /* -1 because of the increment above */
|
||||
}
|
||||
}
|
||||
|
||||
*r++ = '\'';
|
||||
|
@ -266,6 +295,37 @@ ansic_quote (str, flags, rlen)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
int
|
||||
ansic_wshouldquote (string)
|
||||
const char *string;
|
||||
{
|
||||
const wchar_t *wcs;
|
||||
wchar_t wcc;
|
||||
|
||||
wchar_t *wcstr = NULL;
|
||||
size_t slen;
|
||||
|
||||
|
||||
slen = mbstowcs (wcstr, string, 0);
|
||||
|
||||
if (slen == -1)
|
||||
slen = 0;
|
||||
wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (slen + 1));
|
||||
mbstowcs (wcstr, string, slen + 1);
|
||||
|
||||
for (wcs = wcstr; wcc = *wcs; wcs++)
|
||||
if (iswprint(wcc) == 0)
|
||||
{
|
||||
free (wcstr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
free (wcstr);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* return 1 if we need to quote with $'...' because of non-printing chars. */
|
||||
int
|
||||
ansic_shouldquote (string)
|
||||
|
@ -278,8 +338,14 @@ ansic_shouldquote (string)
|
|||
return 0;
|
||||
|
||||
for (s = string; c = *s; s++)
|
||||
if (ISPRINT (c) == 0)
|
||||
return 1;
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (is_basic (c) == 0)
|
||||
return (ansic_wshouldquote (s));
|
||||
#endif
|
||||
if (ISPRINT (c) == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <bashansi.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
@ -135,7 +137,7 @@ sh_mktmpname (nameroot, flags)
|
|||
filenum = (filenum << 1) ^
|
||||
(unsigned long) time ((time_t *)0) ^
|
||||
(unsigned long) dollar_dollar_pid ^
|
||||
(unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++);
|
||||
(unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++);
|
||||
sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
|
||||
if (tmpnamelen > 0 && tmpnamelen < 32)
|
||||
filename[tdlen + 1 + tmpnamelen] = '\0';
|
||||
|
@ -184,7 +186,7 @@ sh_mktmpfd (nameroot, flags, namep)
|
|||
filenum = (filenum << 1) ^
|
||||
(unsigned long) time ((time_t *)0) ^
|
||||
(unsigned long) dollar_dollar_pid ^
|
||||
(unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++);
|
||||
(unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++);
|
||||
sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
|
||||
if (tmpnamelen > 0 && tmpnamelen < 32)
|
||||
filename[tdlen + 1 + tmpnamelen] = '\0';
|
||||
|
|
188
lib/sh/unicode.c
188
lib/sh/unicode.c
|
@ -1,6 +1,6 @@
|
|||
/* unicode.c - functions to convert unicode characters */
|
||||
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
|||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#if HAVE_ICONV
|
||||
|
@ -61,6 +62,8 @@ static iconv_t localconv;
|
|||
#endif
|
||||
|
||||
#ifndef HAVE_LOCALE_CHARSET
|
||||
static char charsetbuf[40];
|
||||
|
||||
static char *
|
||||
stub_charset ()
|
||||
{
|
||||
|
@ -68,32 +71,46 @@ stub_charset ()
|
|||
|
||||
locale = get_locale_var ("LC_CTYPE");
|
||||
if (locale == 0 || *locale == 0)
|
||||
return "ASCII";
|
||||
{
|
||||
strcpy (charsetbuf, "ASCII");
|
||||
return charsetbuf;
|
||||
}
|
||||
s = strrchr (locale, '.');
|
||||
if (s)
|
||||
{
|
||||
t = strchr (s, '@');
|
||||
strcpy (charsetbuf, s+1);
|
||||
t = strchr (charsetbuf, '@');
|
||||
if (t)
|
||||
*t = 0;
|
||||
return ++s;
|
||||
return charsetbuf;
|
||||
}
|
||||
else if (STREQ (locale, "UTF-8"))
|
||||
return "UTF-8";
|
||||
else
|
||||
return "ASCII";
|
||||
strcpy (charsetbuf, locale);
|
||||
return charsetbuf;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
u32reset ()
|
||||
{
|
||||
#if defined (HAVE_ICONV)
|
||||
if (u32init && localconv != (iconv_t)-1)
|
||||
{
|
||||
iconv_close (localconv);
|
||||
localconv = (iconv_t)-1;
|
||||
}
|
||||
#endif
|
||||
u32init = 0;
|
||||
utf8locale = 0;
|
||||
}
|
||||
|
||||
/* u32toascii ? */
|
||||
int
|
||||
u32tochar (wc, s)
|
||||
wchar_t wc;
|
||||
u32tochar (x, s)
|
||||
unsigned long x;
|
||||
char *s;
|
||||
{
|
||||
unsigned long x;
|
||||
int l;
|
||||
|
||||
x = wc;
|
||||
l = (x <= UCHAR_MAX) ? 1 : ((x <= USHORT_MAX) ? 2 : 4);
|
||||
|
||||
if (x <= UCHAR_MAX)
|
||||
|
@ -115,31 +132,107 @@ u32tochar (wc, s)
|
|||
}
|
||||
|
||||
int
|
||||
u32toutf8 (wc, s)
|
||||
wchar_t wc;
|
||||
u32tocesc (wc, s)
|
||||
u_bits32_t wc;
|
||||
char *s;
|
||||
{
|
||||
int l;
|
||||
|
||||
l = (wc < 0x0080) ? 1 : ((wc < 0x0800) ? 2 : 3);
|
||||
if (wc < 0x10000)
|
||||
l = sprintf (s, "\\u%04X", wc);
|
||||
else
|
||||
l = sprintf (s, "\\u%08X", wc);
|
||||
return l;
|
||||
}
|
||||
|
||||
/* Convert unsigned 32-bit int to utf-8 character string */
|
||||
int
|
||||
u32toutf8 (wc, s)
|
||||
u_bits32_t wc;
|
||||
char *s;
|
||||
{
|
||||
int l;
|
||||
|
||||
if (wc < 0x0080)
|
||||
s[0] = (unsigned char)wc;
|
||||
{
|
||||
s[0] = (char)wc;
|
||||
l = 1;
|
||||
}
|
||||
else if (wc < 0x0800)
|
||||
{
|
||||
s[0] = (wc >> 6) | 0xc0;
|
||||
s[1] = (wc & 0x3f) | 0x80;
|
||||
l = 2;
|
||||
}
|
||||
else
|
||||
else if (wc < 0x10000)
|
||||
{
|
||||
/* Technically, we could return 0 here if 0xd800 <= wc <= 0x0dfff */
|
||||
s[0] = (wc >> 12) | 0xe0;
|
||||
s[1] = ((wc >> 6) & 0x3f) | 0x80;
|
||||
s[2] = (wc & 0x3f) | 0x80;
|
||||
l = 3;
|
||||
}
|
||||
else if (wc < 0x200000)
|
||||
{
|
||||
s[0] = (wc >> 18) | 0xf0;
|
||||
s[1] = ((wc >> 12) & 0x3f) | 0x80;
|
||||
s[2] = ((wc >> 6) & 0x3f) | 0x80;
|
||||
s[3] = (wc & 0x3f) | 0x80;
|
||||
l = 4;
|
||||
}
|
||||
/* Strictly speaking, UTF-8 doesn't have characters longer than 4 bytes */
|
||||
else if (wc < 0x04000000)
|
||||
{
|
||||
s[0] = (wc >> 24) | 0xf8;
|
||||
s[1] = ((wc >> 18) & 0x3f) | 0x80;
|
||||
s[2] = ((wc >> 12) & 0x3f) | 0x80;
|
||||
s[3] = ((wc >> 6) & 0x3f) | 0x80;
|
||||
s[4] = (wc & 0x3f) | 0x80;
|
||||
l = 5;
|
||||
}
|
||||
else if (wc < 0x080000000)
|
||||
{
|
||||
s[0] = (wc >> 30) | 0xf8;
|
||||
s[1] = ((wc >> 24) & 0x3f) | 0x80;
|
||||
s[2] = ((wc >> 18) & 0x3f) | 0x80;
|
||||
s[3] = ((wc >> 12) & 0x3f) | 0x80;
|
||||
s[4] = ((wc >> 6) & 0x3f) | 0x80;
|
||||
s[5] = (wc & 0x3f) | 0x80;
|
||||
l = 6;
|
||||
}
|
||||
else
|
||||
l = 0;
|
||||
|
||||
s[l] = '\0';
|
||||
return l;
|
||||
}
|
||||
|
||||
/* Convert a 32-bit unsigned int (unicode) to a UTF-16 string. Rarely used,
|
||||
only if sizeof(wchar_t) == 2. */
|
||||
int
|
||||
u32toutf16 (c, s)
|
||||
u_bits32_t c;
|
||||
unsigned short *s;
|
||||
{
|
||||
int l;
|
||||
|
||||
l = 0;
|
||||
if (c < 0x0d800)
|
||||
{
|
||||
s[0] = (unsigned short) (c & 0xFFFF);
|
||||
l = 1;
|
||||
}
|
||||
else if (c >= 0x0e000 && c <= 0x010ffff)
|
||||
{
|
||||
c -= 0x010000;
|
||||
s[0] = (unsigned short)((c >> 10) + 0xd800);
|
||||
s[1] = (unsigned short)((c & 0x3ff) + 0xdc00);
|
||||
l = 2;
|
||||
}
|
||||
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
|
||||
|
@ -148,6 +241,7 @@ u32cconv (c, s)
|
|||
char *s;
|
||||
{
|
||||
wchar_t wc;
|
||||
wchar_t ws[3];
|
||||
int n;
|
||||
#if HAVE_ICONV
|
||||
const char *charset;
|
||||
|
@ -157,21 +251,23 @@ u32cconv (c, s)
|
|||
size_t sn;
|
||||
#endif
|
||||
|
||||
wc = c;
|
||||
|
||||
#if __STDC_ISO_10646__
|
||||
if (sizeof (wchar_t) == 4)
|
||||
{
|
||||
n = wctomb (s, wc);
|
||||
return n;
|
||||
}
|
||||
wc = c;
|
||||
if (sizeof (wchar_t) == 4 && c <= 0x7fffffff)
|
||||
n = wctomb (s, wc);
|
||||
else if (sizeof (wchar_t) == 2 && c <= 0x10ffff && u32toutf16 (c, ws))
|
||||
n = wcstombs (s, ws, MB_LEN_MAX);
|
||||
else
|
||||
n = -1;
|
||||
if (n != -1)
|
||||
return n;
|
||||
#endif
|
||||
|
||||
#if HAVE_NL_LANGINFO
|
||||
codeset = nl_langinfo (CODESET);
|
||||
if (STREQ (codeset, "UTF-8"))
|
||||
{
|
||||
n = u32toutf8 (wc, s);
|
||||
n = u32toutf8 (c, s);
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
@ -191,25 +287,23 @@ u32cconv (c, s)
|
|||
{
|
||||
localconv = iconv_open (charset, "UTF-8");
|
||||
if (localconv == (iconv_t)-1)
|
||||
localconv = iconv_open (charset, "ASCII");
|
||||
/* We assume ASCII when presented with an unknown encoding. */
|
||||
localconv = iconv_open ("ASCII", "UTF-8");
|
||||
}
|
||||
u32init = 1;
|
||||
}
|
||||
|
||||
/* If we have a UTF-8 locale, convert to UTF-8 and return converted value. */
|
||||
n = u32toutf8 (c, s);
|
||||
if (utf8locale)
|
||||
{
|
||||
n = u32toutf8 (wc, s);
|
||||
return n;
|
||||
}
|
||||
return n;
|
||||
|
||||
/* If the conversion is not supported, even the ASCII requested above, we
|
||||
bail now. Currently we return the UTF-8 conversion. We could return
|
||||
u32tocesc(). */
|
||||
if (localconv == (iconv_t)-1)
|
||||
{
|
||||
n = u32tochar (wc, s);
|
||||
return n;
|
||||
}
|
||||
|
||||
n = u32toutf8 (wc, s);
|
||||
|
||||
return n;
|
||||
|
||||
optr = obuf;
|
||||
obytesleft = sizeof (obuf);
|
||||
iptr = s;
|
||||
|
@ -218,7 +312,15 @@ u32cconv (c, s)
|
|||
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 */
|
||||
{
|
||||
#if 1
|
||||
/* You get ISO C99 escape sequences if iconv fails */
|
||||
n = u32tocesc (c, s);
|
||||
#else
|
||||
/* You get UTF-8 if iconv fails */
|
||||
#endif
|
||||
return n;
|
||||
}
|
||||
|
||||
*optr = '\0';
|
||||
|
||||
|
@ -226,10 +328,14 @@ u32cconv (c, s)
|
|||
checking */
|
||||
strcpy (s, obuf);
|
||||
return (optr - obuf);
|
||||
#endif
|
||||
#endif /* HAVE_ICONV */
|
||||
|
||||
n = u32tochar (wc, s); /* fallback */
|
||||
n = u32tocesc (c, s); /* fallback is ISO C99 escape sequences */
|
||||
return n;
|
||||
}
|
||||
|
||||
#else
|
||||
void
|
||||
u32reset ()
|
||||
{
|
||||
}
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
|
56
lib/sh/wcsnwidth.c
Normal file
56
lib/sh/wcsnwidth.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* wcsnwidth.c - compute display width of wide character string, up to max
|
||||
specified width, return length. */
|
||||
|
||||
/* Copyright (C) 2012 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>
|
||||
|
||||
/* Return the number of wide characters that will be displayed from wide string
|
||||
PWCS. If the display width exceeds MAX, return the number of wide chars
|
||||
from PWCS required to display MAX characters on the screen. */
|
||||
int
|
||||
wcsnwidth(pwcs, n, max)
|
||||
const wchar_t *pwcs;
|
||||
size_t n, max;
|
||||
{
|
||||
wchar_t wc, *ws;
|
||||
int len, l;
|
||||
|
||||
len = 0;
|
||||
ws = (wchar_t *)pwcs;
|
||||
while (n-- > 0 && (wc = *ws++) != L'\0')
|
||||
{
|
||||
l = wcwidth (wc);
|
||||
if (l < 0)
|
||||
return (-1);
|
||||
else if (l == max - len)
|
||||
return (ws - pwcs);
|
||||
else if (l > max - len)
|
||||
return (--ws - pwcs);
|
||||
len += l;
|
||||
}
|
||||
return (ws - pwcs);
|
||||
}
|
||||
#endif
|
|
@ -50,7 +50,7 @@ typedef ssize_t creadfunc_t __P((int, char *));
|
|||
The differences are
|
||||
(1) using file descriptor instead of FILE *,
|
||||
(2) the order of arguments; the file descriptor comes the first, and
|
||||
(3) the addtion of thired argument, UNBUFFERED_READ; this argument
|
||||
(3) the addition of third argument, UNBUFFERED_READ; this argument
|
||||
controls whether get_line uses buffering or not to get a byte data
|
||||
from FD. get_line uses zreadc if UNBUFFERED_READ is zero; and
|
||||
uses zread if UNBUFFERED_READ is non-zero.
|
||||
|
|
|
@ -66,11 +66,10 @@ zmapfd (fd, ostr, fn)
|
|||
}
|
||||
else if (nr < 0)
|
||||
{
|
||||
rval = -1;
|
||||
free (result);
|
||||
if (ostr)
|
||||
*ostr = (char *)NULL;
|
||||
break;
|
||||
return -1;
|
||||
}
|
||||
|
||||
RESIZE_MALLOCED_BUFFER (result, rind, nr, rsize, 128);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if !defined (errno)
|
||||
|
@ -36,6 +37,9 @@ extern int errno;
|
|||
# define SEEK_CUR 1
|
||||
#endif
|
||||
|
||||
extern void check_signals_and_traps (void);
|
||||
extern int signal_is_trapped (int);
|
||||
|
||||
/* Read LEN bytes from FD into BUF. Retry the read on EINTR. Any other
|
||||
error causes the loop to break. */
|
||||
ssize_t
|
||||
|
@ -46,8 +50,22 @@ zread (fd, buf, len)
|
|||
{
|
||||
ssize_t r;
|
||||
|
||||
#if 0
|
||||
#if defined (HAVE_SIGINTERRUPT)
|
||||
if (signal_is_trapped (SIGCHLD))
|
||||
siginterrupt (SIGCHLD, 1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while ((r = read (fd, buf, len)) < 0 && errno == EINTR)
|
||||
;
|
||||
check_signals_and_traps (); /* XXX - should it be check_signals()? */
|
||||
|
||||
#if 0
|
||||
#if defined (HAVE_SIGINTERRUPT)
|
||||
siginterrupt (SIGCHLD, 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -148,6 +166,34 @@ zreadcintr (fd, cp)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Like zreadc, but read a specified number of characters at a time. Used
|
||||
for `read -N'. */
|
||||
ssize_t
|
||||
zreadn (fd, cp, len)
|
||||
int fd;
|
||||
char *cp;
|
||||
size_t len;
|
||||
{
|
||||
ssize_t nr;
|
||||
|
||||
if (lind == lused || lused == 0)
|
||||
{
|
||||
if (len > sizeof (lbuf))
|
||||
len = sizeof (lbuf);
|
||||
nr = zread (fd, lbuf, len);
|
||||
lind = 0;
|
||||
if (nr <= 0)
|
||||
{
|
||||
lused = 0;
|
||||
return nr;
|
||||
}
|
||||
lused = nr;
|
||||
}
|
||||
if (cp)
|
||||
*cp = lbuf[lind++];
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
zreset ()
|
||||
{
|
||||
|
|
|
@ -55,15 +55,26 @@ get_env_value (varname)
|
|||
return ((char *)getenv (varname));
|
||||
}
|
||||
|
||||
/* If we're not using $HOME, assume that the passwd file information won't
|
||||
change while this shell instance is running. */
|
||||
char *
|
||||
get_home_dir ()
|
||||
{
|
||||
char *home_dir;
|
||||
static char *home_dir = (char *)NULL;
|
||||
struct passwd *entry;
|
||||
|
||||
home_dir = (char *)NULL;
|
||||
if (home_dir)
|
||||
return (home_dir);
|
||||
|
||||
#if defined (HAVE_GETPWUID)
|
||||
entry = getpwuid (getuid ());
|
||||
if (entry)
|
||||
home_dir = entry->pw_dir;
|
||||
home_dir = savestring (entry->pw_dir);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_GETPWENT)
|
||||
endpwent (); /* some systems need this */
|
||||
#endif
|
||||
|
||||
return (home_dir);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue