Imported from ../bash-3.2.48.tar.gz.
This commit is contained in:
parent
0628567a28
commit
f1be666c7d
47 changed files with 703 additions and 159 deletions
42
array.c
42
array.c
|
@ -120,7 +120,6 @@ ARRAY *a;
|
|||
return(a1);
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_UNUSED
|
||||
/*
|
||||
* Make and return a new array composed of the elements in array A from
|
||||
* S to E, inclusive.
|
||||
|
@ -141,13 +140,12 @@ ARRAY_ELEMENT *s, *e;
|
|||
for (p = s, i = 0; p != e; p = element_forw(p), i++) {
|
||||
n = array_create_element (element_index(p), element_value(p));
|
||||
ADD_BEFORE(a->head, n);
|
||||
mi = element_index(ae);
|
||||
mi = element_index(n);
|
||||
}
|
||||
a->num_elements = i;
|
||||
a->max_index = mi;
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Walk the array, calling FUNC once for each element, with the array
|
||||
|
@ -300,6 +298,23 @@ ARRAY *array;
|
|||
return array;
|
||||
}
|
||||
|
||||
ARRAY *
|
||||
array_quote_escapes(array)
|
||||
ARRAY *array;
|
||||
{
|
||||
ARRAY_ELEMENT *a;
|
||||
char *t;
|
||||
|
||||
if (array == 0 || array_head(array) == 0 || array_empty(array))
|
||||
return (ARRAY *)NULL;
|
||||
for (a = element_forw(array->head); a != array->head; a = element_forw(a)) {
|
||||
t = quote_escapes (a->value);
|
||||
FREE(a->value);
|
||||
a->value = t;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a string whose elements are the members of array A beginning at
|
||||
* index START and spanning NELEM members. Null elements are counted.
|
||||
|
@ -311,9 +326,10 @@ ARRAY *a;
|
|||
arrayind_t start, nelem;
|
||||
int starsub, quoted;
|
||||
{
|
||||
ARRAY *a2;
|
||||
ARRAY_ELEMENT *h, *p;
|
||||
arrayind_t i;
|
||||
char *ifs, sep[2];
|
||||
char *ifs, sep[2], *t;
|
||||
|
||||
p = a ? array_head (a) : 0;
|
||||
if (p == 0 || array_empty (a) || start > array_max_index(a))
|
||||
|
@ -336,6 +352,13 @@ int starsub, quoted;
|
|||
for (i = 0, h = p; p != a->head && i < nelem; i++, p = element_forw(p))
|
||||
;
|
||||
|
||||
a2 = array_slice(a, h, p);
|
||||
|
||||
if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
|
||||
array_quote(a2);
|
||||
else
|
||||
array_quote_escapes(a2);
|
||||
|
||||
if (starsub && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) {
|
||||
ifs = getifs();
|
||||
sep[0] = ifs ? *ifs : '\0';
|
||||
|
@ -343,7 +366,10 @@ int starsub, quoted;
|
|||
sep[0] = ' ';
|
||||
sep[1] = '\0';
|
||||
|
||||
return (array_to_string_internal (h, p, sep, quoted));
|
||||
t = array_to_string (a2, sep, 0);
|
||||
array_dispose(a2);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
char *
|
||||
|
@ -367,7 +393,9 @@ int mflags;
|
|||
}
|
||||
|
||||
if (mflags & MATCH_QUOTED)
|
||||
array_quote (a2);
|
||||
array_quote(a2);
|
||||
else
|
||||
array_quote_escapes(a2);
|
||||
if (mflags & MATCH_STARSUB) {
|
||||
ifs = getifs();
|
||||
sifs[0] = ifs ? *ifs : '\0';
|
||||
|
@ -655,7 +683,7 @@ int quoted;
|
|||
is = inttostr (element_index(ae), indstr, sizeof(indstr));
|
||||
valstr = element_value (ae) ? sh_double_quote (element_value(ae))
|
||||
: (char *)NULL;
|
||||
elen = STRLEN (indstr) + 8 + STRLEN (valstr);
|
||||
elen = STRLEN (is) + 8 + STRLEN (valstr);
|
||||
RESIZE_MALLOCED_BUFFER (result, rlen, (elen + 1), rsize, rsize);
|
||||
|
||||
result[rlen++] = '[';
|
||||
|
|
1
array.h
1
array.h
|
@ -55,6 +55,7 @@ extern int array_rshift __P((ARRAY *, int, char *));
|
|||
extern ARRAY_ELEMENT *array_unshift_element __P((ARRAY *));
|
||||
extern int array_shift_element __P((ARRAY *, char *));
|
||||
extern ARRAY *array_quote __P((ARRAY *));
|
||||
extern ARRAY *array_quote_escapes __P((ARRAY *));
|
||||
|
||||
extern char *array_subrange __P((ARRAY *, arrayind_t, arrayind_t, int, int));
|
||||
extern char *array_patsub __P((ARRAY *, char *, char *, int));
|
||||
|
|
|
@ -618,6 +618,8 @@ array_expand_index (s, len)
|
|||
if (expok == 0)
|
||||
{
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
|
||||
top_level_cleanup ();
|
||||
jump_to_top_level (DISCARD);
|
||||
}
|
||||
return val;
|
||||
|
@ -720,7 +722,7 @@ array_value_internal (s, quoted, allow_all, rtype)
|
|||
if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
|
||||
{
|
||||
if (rtype)
|
||||
*rtype = 1;
|
||||
*rtype = (t[0] == '*') ? 1 : 2;
|
||||
if (allow_all == 0)
|
||||
{
|
||||
err_badarraysub (s);
|
||||
|
|
|
@ -80,6 +80,7 @@ static struct ignorevar histignore =
|
|||
list. This is different than the user-controlled behaviour; this
|
||||
becomes zero when we read lines from a file, for example. */
|
||||
int remember_on_history = 1;
|
||||
int enable_history_list = 1; /* value for `set -o history' */
|
||||
|
||||
/* The number of lines that Bash has added to this history session. The
|
||||
difference between the number of the top element in the history list
|
||||
|
@ -234,7 +235,7 @@ bash_history_reinit (interact)
|
|||
history_expansion = interact != 0;
|
||||
history_expansion_inhibited = 1;
|
||||
#endif
|
||||
remember_on_history = interact != 0;
|
||||
remember_on_history = enable_history_list = interact != 0;
|
||||
history_inhibit_expansion_function = bash_history_inhibit_expansion;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#define HC_IGNBOTH (HC_IGNSPACE|HC_IGNDUPS)
|
||||
|
||||
extern int remember_on_history;
|
||||
extern int enable_history_list; /* value for `set -o history' */
|
||||
extern int literal_history; /* controlled by `shopt lithist' */
|
||||
extern int force_append_history;
|
||||
extern int history_lines_this_session;
|
||||
extern int history_lines_in_file;
|
||||
extern int history_expansion;
|
||||
|
|
|
@ -2357,7 +2357,7 @@ bash_directory_completion_hook (dirname)
|
|||
if (should_expand_dirname)
|
||||
{
|
||||
new_dirname = savestring (local_dirname);
|
||||
wl = expand_prompt_string (new_dirname, 0); /* does the right thing */
|
||||
wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB); /* does the right thing */
|
||||
if (wl)
|
||||
{
|
||||
*dirname = string_list (wl);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -131,6 +131,7 @@ no_args (list)
|
|||
if (list)
|
||||
{
|
||||
builtin_error (_("too many arguments"));
|
||||
top_level_cleanup ();
|
||||
jump_to_top_level (DISCARD);
|
||||
}
|
||||
}
|
||||
|
@ -395,7 +396,10 @@ get_numeric_arg (list, fatal)
|
|||
if (fatal)
|
||||
throw_to_top_level ();
|
||||
else
|
||||
jump_to_top_level (DISCARD);
|
||||
{
|
||||
top_level_cleanup ();
|
||||
jump_to_top_level (DISCARD);
|
||||
}
|
||||
}
|
||||
no_args (list->next);
|
||||
}
|
||||
|
@ -475,7 +479,11 @@ get_working_directory (for_whom)
|
|||
|
||||
if (the_current_working_directory == 0)
|
||||
{
|
||||
#if defined (GETCWD_BROKEN)
|
||||
the_current_working_directory = getcwd (0, PATH_MAX);
|
||||
#else
|
||||
the_current_working_directory = getcwd (0, 0);
|
||||
#endif
|
||||
if (the_current_working_directory == 0)
|
||||
{
|
||||
fprintf (stderr, _("%s: error retrieving current directory: %s: %s\n"),
|
||||
|
|
|
@ -67,6 +67,14 @@ int parse_and_execute_level = 0;
|
|||
|
||||
static int cat_file __P((REDIRECT *));
|
||||
|
||||
#if defined (HISTORY)
|
||||
static void
|
||||
set_history_remembering ()
|
||||
{
|
||||
remember_on_history = enable_history_list;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* How to force parse_and_execute () to clean up after itself. */
|
||||
void
|
||||
parse_and_execute_cleanup ()
|
||||
|
@ -115,7 +123,10 @@ parse_and_execute (string, from_file, flags)
|
|||
lreset = flags & SEVAL_RESETLINE;
|
||||
|
||||
#if defined (HISTORY)
|
||||
unwind_protect_int (remember_on_history); /* can be used in scripts */
|
||||
if (parse_and_execute_level == 0)
|
||||
add_unwind_protect (set_history_remembering, (char *)NULL);
|
||||
else
|
||||
unwind_protect_int (remember_on_history); /* can be used in scripts */
|
||||
# if defined (BANG_HISTORY)
|
||||
if (interactive_shell)
|
||||
{
|
||||
|
@ -237,6 +248,7 @@ parse_and_execute (string, from_file, flags)
|
|||
* parse_and_execute has not been called recursively AND
|
||||
* we're not running a trap AND
|
||||
* we have parsed the full command (string == '\0') AND
|
||||
* we're not going to run the exit trap AND
|
||||
* we have a simple command without redirections AND
|
||||
* the command is not being timed AND
|
||||
* the command's return status is not being inverted
|
||||
|
@ -247,7 +259,8 @@ parse_and_execute (string, from_file, flags)
|
|||
running_trap == 0 &&
|
||||
*bash_input.location.string == '\0' &&
|
||||
command->type == cm_simple &&
|
||||
!command->redirects && !command->value.Simple->redirects &&
|
||||
signal_is_trapped (EXIT_TRAP) == 0 &&
|
||||
command->redirects == 0 && command->value.Simple->redirects == 0 &&
|
||||
((command->flags & CMD_TIME_PIPELINE) == 0) &&
|
||||
((command->flags & CMD_INVERT_RETURN) == 0))
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
This file is printf.def, from which is created printf.c.
|
||||
It implements the builtin "printf" in Bash.
|
||||
|
||||
Copyright (C) 1997-2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -49,6 +49,12 @@ $END
|
|||
# define INT_MIN (-2147483647-1)
|
||||
#endif
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <chartypes.h>
|
||||
|
||||
|
@ -64,6 +70,10 @@ $END
|
|||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
#if defined (PRI_MACROS_BROKEN)
|
||||
# undef PRIdMAX
|
||||
#endif
|
||||
|
||||
#if !defined (PRIdMAX)
|
||||
# if HAVE_LONG_LONG
|
||||
# define PRIdMAX "lld"
|
||||
|
@ -151,6 +161,10 @@ extern int errno;
|
|||
#define SKIP1 "#'-+ 0"
|
||||
#define LENMODS "hjlLtz"
|
||||
|
||||
#ifndef HAVE_ASPRINTF
|
||||
extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
|
||||
#endif
|
||||
|
||||
static void printf_erange __P((char *));
|
||||
static int printstr __P((char *, char *, int, int, int));
|
||||
static int tescape __P((char *, char *, int *));
|
||||
|
|
|
@ -127,14 +127,14 @@ read_builtin (list)
|
|||
WORD_LIST *list;
|
||||
{
|
||||
register char *varname;
|
||||
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code;
|
||||
int input_is_tty, input_is_pipe, unbuffered_read;
|
||||
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
|
||||
int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
|
||||
int raw, edit, nchars, silent, have_timeout, fd;
|
||||
unsigned int tmout;
|
||||
intmax_t intval;
|
||||
char c;
|
||||
char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
|
||||
char *e, *t, *t1;
|
||||
char *e, *t, *t1, *ps2, *tofree;
|
||||
struct stat tsb;
|
||||
SHELL_VAR *var;
|
||||
#if defined (ARRAY_VARS)
|
||||
|
@ -148,6 +148,7 @@ read_builtin (list)
|
|||
USE_VAR(size);
|
||||
USE_VAR(i);
|
||||
USE_VAR(pass_next);
|
||||
USE_VAR(print_ps2);
|
||||
USE_VAR(saw_escape);
|
||||
USE_VAR(input_is_pipe);
|
||||
/* USE_VAR(raw); */
|
||||
|
@ -163,6 +164,7 @@ read_builtin (list)
|
|||
USE_VAR(rlind);
|
||||
#endif
|
||||
USE_VAR(list);
|
||||
USE_VAR(ps2);
|
||||
|
||||
i = 0; /* Index into the string that we are reading. */
|
||||
raw = edit = 0; /* Not reading raw input by default. */
|
||||
|
@ -386,7 +388,8 @@ read_builtin (list)
|
|||
setmode (0, O_TEXT);
|
||||
#endif
|
||||
|
||||
for (eof = retval = 0;;)
|
||||
ps2 = 0;
|
||||
for (print_ps2 = eof = retval = 0;;)
|
||||
{
|
||||
#if defined (READLINE)
|
||||
if (edit)
|
||||
|
@ -412,6 +415,15 @@ read_builtin (list)
|
|||
{
|
||||
#endif
|
||||
|
||||
if (print_ps2)
|
||||
{
|
||||
if (ps2 == 0)
|
||||
ps2 = get_string_value ("PS2");
|
||||
fprintf (stderr, "%s", ps2 ? ps2 : "");
|
||||
fflush (stderr);
|
||||
print_ps2 = 0;
|
||||
}
|
||||
|
||||
if (unbuffered_read)
|
||||
retval = zread (fd, &c, 1);
|
||||
else
|
||||
|
@ -440,7 +452,11 @@ read_builtin (list)
|
|||
{
|
||||
pass_next = 0;
|
||||
if (c == '\n')
|
||||
i--; /* back up over the CTLESC */
|
||||
{
|
||||
i--; /* back up over the CTLESC */
|
||||
if (interactive && input_is_tty && raw == 0)
|
||||
print_ps2 = 1;
|
||||
}
|
||||
else
|
||||
goto add_char;
|
||||
continue;
|
||||
|
@ -658,12 +674,13 @@ add_char:
|
|||
#else
|
||||
/* Check whether or not the number of fields is exactly the same as the
|
||||
number of variables. */
|
||||
tofree = NULL;
|
||||
if (*input_string)
|
||||
{
|
||||
t1 = input_string;
|
||||
t = get_word_from_string (&input_string, ifs_chars, &e);
|
||||
if (*input_string == 0)
|
||||
input_string = t;
|
||||
tofree = input_string = t;
|
||||
else
|
||||
input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
|
||||
}
|
||||
|
@ -678,6 +695,8 @@ add_char:
|
|||
else
|
||||
var = bind_read_variable (list->word->word, input_string);
|
||||
stupidly_hack_special_variables (list->word->word);
|
||||
FREE (tofree);
|
||||
|
||||
if (var)
|
||||
VUNSETATTR (var, att_invisible);
|
||||
xfree (orig_input_string);
|
||||
|
|
|
@ -189,7 +189,7 @@ struct {
|
|||
{ "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
|
||||
#endif /* BANG_HISTORY */
|
||||
#if defined (HISTORY)
|
||||
{ "history", '\0', &remember_on_history, bash_set_history, (setopt_get_func_t *)NULL },
|
||||
{ "history", '\0', &enable_history_list, bash_set_history, (setopt_get_func_t *)NULL },
|
||||
#endif
|
||||
{ "ignoreeof", '\0', &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL },
|
||||
{ "interactive-comments", '\0', &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
|
||||
|
@ -381,13 +381,17 @@ bash_set_history (on_or_off, option_name)
|
|||
{
|
||||
if (on_or_off == FLAG_ON)
|
||||
{
|
||||
enable_history_list = 1;
|
||||
bash_history_enable ();
|
||||
if (history_lines_this_session == 0)
|
||||
load_history ();
|
||||
}
|
||||
else
|
||||
bash_history_disable ();
|
||||
return (1 - remember_on_history);
|
||||
{
|
||||
enable_history_list = 0;
|
||||
bash_history_disable ();
|
||||
}
|
||||
return (1 - enable_history_list);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -565,7 +569,7 @@ void
|
|||
reset_shell_options ()
|
||||
{
|
||||
#if defined (HISTORY)
|
||||
remember_on_history = 1;
|
||||
remember_on_history = enable_history_list = 1;
|
||||
#endif
|
||||
ignoreeof = 0;
|
||||
}
|
||||
|
|
|
@ -101,11 +101,14 @@ static void shopt_error __P((char *));
|
|||
|
||||
static int set_shellopts_after_change __P((int));
|
||||
|
||||
static int set_compatibility_level __P((int));
|
||||
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
static int set_restricted_shell __P((int));
|
||||
#endif
|
||||
|
||||
static int shopt_login_shell;
|
||||
static int shopt_compat31;
|
||||
|
||||
typedef int shopt_set_func_t __P((int));
|
||||
|
||||
|
@ -121,6 +124,7 @@ static struct {
|
|||
#if defined (HISTORY)
|
||||
{ "cmdhist", &command_oriented_history, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "compat31", &shopt_compat31, set_compatibility_level },
|
||||
{ "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL },
|
||||
{ "execfail", &no_exit_on_failed_exec, (shopt_set_func_t *)NULL },
|
||||
{ "expand_aliases", &expand_aliases, (shopt_set_func_t *)NULL },
|
||||
|
@ -459,6 +463,18 @@ set_shellopts_after_change (mode)
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
set_compatibility_level (mode)
|
||||
int mode;
|
||||
{
|
||||
/* Need to change logic here as we add more compatibility levels */
|
||||
if (shopt_compat31)
|
||||
shell_compatibility_level = 31;
|
||||
else
|
||||
shell_compatibility_level = 32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
/* Don't allow the value of restricted_shell to be modified. */
|
||||
|
||||
|
|
10
config-bot.h
10
config-bot.h
|
@ -1,7 +1,7 @@
|
|||
/* config-bot.h */
|
||||
/* modify settings or make new ones based on what autoconf tells us. */
|
||||
|
||||
/* Copyright (C) 1989-2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -70,9 +70,11 @@
|
|||
# define TERMIOS_MISSING
|
||||
#endif
|
||||
|
||||
/* If we have a getcwd(3), but it calls popen(), #undef HAVE_GETCWD so
|
||||
the replacement in getcwd.c will be built. */
|
||||
#if defined (HAVE_GETCWD) && defined (GETCWD_BROKEN)
|
||||
/* If we have a getcwd(3), but one that does not dynamically allocate memory,
|
||||
#undef HAVE_GETCWD so the replacement in getcwd.c will be built. We do
|
||||
not do this on Solaris, because their implementation of loopback mounts
|
||||
breaks the traditional file system assumptions that getcwd uses. */
|
||||
#if defined (HAVE_GETCWD) && defined (GETCWD_BROKEN) && !defined (SOLARIS)
|
||||
# undef HAVE_GETCWD
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* config.h -- Configuration file for bash. */
|
||||
|
||||
/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -413,6 +413,8 @@
|
|||
|
||||
#undef HAVE_DECL_STRTOLD
|
||||
|
||||
#undef PRI_MACROS_BROKEN
|
||||
|
||||
#undef STRTOLD_BROKEN
|
||||
|
||||
/* Define if WCONTINUED is defined in system headers, but rejected by waitpid */
|
||||
|
@ -1006,6 +1008,9 @@
|
|||
/* Define if you have the `dcgettext' function. */
|
||||
#undef HAVE_DCGETTEXT
|
||||
|
||||
/* Define if you have the `localeconv' function. */
|
||||
#undef HAVE_LOCALECONV
|
||||
|
||||
/* Define if your system has a working `malloc' function. */
|
||||
/* #undef HAVE_MALLOC */
|
||||
|
||||
|
|
5
configure
vendored
5
configure
vendored
|
@ -4871,7 +4871,7 @@ _ACEOF
|
|||
# static version specified as -llibname to override the
|
||||
# dynamic version
|
||||
case "${host_os}" in
|
||||
darwin8*) READLINE_LIB='${READLINE_LIBRARY}' ;;
|
||||
darwin[89]*) READLINE_LIB='${READLINE_LIBRARY}' ;;
|
||||
*) READLINE_LIB=-lreadline ;;
|
||||
esac
|
||||
fi
|
||||
|
@ -27316,7 +27316,8 @@ sco3.2v5*) LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DPATH_MAX=1024" ;;
|
|||
sco3.2v4*) LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DPATH_MAX=1024" ;;
|
||||
sco3.2*) LOCAL_CFLAGS=-DMUST_UNBLOCK_CHLD ;;
|
||||
sunos4*) LOCAL_CFLAGS=-DSunOS4 ;;
|
||||
solaris2.5*) LOCAL_CFLAGS=-DSunOS5 ;;
|
||||
solaris2.5*) LOCAL_CFLAGS="-DSunOS5 -DSOLARIS" ;;
|
||||
solaris2*) LOCAL_CFLAGS=-DSOLARIS ;;
|
||||
lynxos*) LOCAL_CFLAGS=-DRECYCLES_PIDS ;;
|
||||
linux*) LOCAL_LDFLAGS=-rdynamic # allow dynamic loading
|
||||
case "`uname -r`" in
|
||||
|
|
|
@ -5,7 +5,7 @@ dnl report bugs to chet@po.cwru.edu
|
|||
dnl
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
# Copyright (C) 1987-2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1987-2007 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
|
||||
|
@ -518,7 +518,7 @@ if test $opt_readline = yes; then
|
|||
# static version specified as -llibname to override the
|
||||
# dynamic version
|
||||
case "${host_os}" in
|
||||
darwin8*) READLINE_LIB='${READLINE_LIBRARY}' ;;
|
||||
darwin[[89]]*) READLINE_LIB='${READLINE_LIBRARY}' ;;
|
||||
*) READLINE_LIB=-lreadline ;;
|
||||
esac
|
||||
fi
|
||||
|
@ -991,7 +991,8 @@ sco3.2v5*) LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DPATH_MAX=1024" ;;
|
|||
sco3.2v4*) LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DPATH_MAX=1024" ;;
|
||||
sco3.2*) LOCAL_CFLAGS=-DMUST_UNBLOCK_CHLD ;;
|
||||
sunos4*) LOCAL_CFLAGS=-DSunOS4 ;;
|
||||
solaris2.5*) LOCAL_CFLAGS=-DSunOS5 ;;
|
||||
solaris2.5*) LOCAL_CFLAGS="-DSunOS5 -DSOLARIS" ;;
|
||||
solaris2*) LOCAL_CFLAGS=-DSOLARIS ;;
|
||||
lynxos*) LOCAL_CFLAGS=-DRECYCLES_PIDS ;;
|
||||
linux*) LOCAL_LDFLAGS=-rdynamic # allow dynamic loading
|
||||
case "`uname -r`" in
|
||||
|
|
|
@ -7977,6 +7977,12 @@ attempts to save all lines of a multiple-line
|
|||
command in the same history entry. This allows
|
||||
easy re-editing of multi-line commands.
|
||||
.TP 8
|
||||
.B compat31
|
||||
If set,
|
||||
.B bash
|
||||
changes its behavior to that of version 3.1 with respect to quoted
|
||||
arguments to the conditional command's =~ operator.
|
||||
.TP 8
|
||||
.B dotglob
|
||||
If set,
|
||||
.B bash
|
||||
|
|
|
@ -3598,6 +3598,11 @@ attempts to save all lines of a multiple-line
|
|||
command in the same history entry. This allows
|
||||
easy re-editing of multi-line commands.
|
||||
|
||||
@item compat31
|
||||
If set, Bash
|
||||
changes its behavior to that of version 3.1 with respect to quoted
|
||||
arguments to the conditional command's =~ operator.
|
||||
|
||||
@item dotglob
|
||||
If set, Bash includes filenames beginning with a `.' in
|
||||
the results of filename expansion.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* execute_cmd.c -- Execute a COMMAND structure. */
|
||||
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -501,8 +501,15 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
|||
volatile int last_pid;
|
||||
volatile int save_line_number;
|
||||
|
||||
#if 0
|
||||
if (command == 0 || breaking || continuing || read_but_dont_execute)
|
||||
return (EXECUTION_SUCCESS);
|
||||
#else
|
||||
if (breaking || continuing)
|
||||
return (last_command_exit_value);
|
||||
if (command == 0 || read_but_dont_execute)
|
||||
return (EXECUTION_SUCCESS);
|
||||
#endif
|
||||
|
||||
QUIT;
|
||||
run_pending_traps ();
|
||||
|
@ -614,7 +621,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
|||
cleanup_redirects (redirection_undo_list);
|
||||
redirection_undo_list = (REDIRECT *)NULL;
|
||||
dispose_exec_redirects ();
|
||||
return (EXECUTION_FAILURE);
|
||||
return (last_command_exit_value = EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (redirection_undo_list)
|
||||
|
@ -2546,7 +2553,8 @@ execute_cond_node (cond)
|
|||
arg1 = cond_expand_word (cond->left->op, 0);
|
||||
if (arg1 == 0)
|
||||
arg1 = nullstr;
|
||||
arg2 = cond_expand_word (cond->right->op, patmatch||rmatch);
|
||||
arg2 = cond_expand_word (cond->right->op,
|
||||
(rmatch && shell_compatibility_level > 31) ? 2 : (patmatch ? 1 : 0));
|
||||
if (arg2 == 0)
|
||||
arg2 = nullstr;
|
||||
|
||||
|
@ -3050,6 +3058,11 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
|
|||
if (command_line == 0)
|
||||
command_line = savestring (the_printed_command_except_trap);
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
if ((subshell_environment & SUBSHELL_COMSUB) && (simple_command->flags & CMD_NO_FORK) && fifos_pending() > 0)
|
||||
simple_command->flags &= ~CMD_NO_FORK;
|
||||
#endif
|
||||
|
||||
execute_disk_command (words, simple_command->redirects, command_line,
|
||||
pipe_in, pipe_out, async, fds_to_close,
|
||||
simple_command->flags);
|
||||
|
@ -3875,6 +3888,8 @@ initialize_subshell ()
|
|||
shell_variables = shell_variables->down;
|
||||
|
||||
clear_unwind_protect_list (0);
|
||||
/* XXX -- are there other things we should be resetting here? */
|
||||
parse_and_execute_level = 0; /* nothing left to restore it */
|
||||
|
||||
/* We're no longer inside a shell function. */
|
||||
variable_context = return_catch_flag = 0;
|
||||
|
|
7
expr.c
7
expr.c
|
@ -286,6 +286,8 @@ expr_unwind ()
|
|||
free (expr_stack[expr_depth]);
|
||||
}
|
||||
free (expr_stack[expr_depth]); /* free the allocated EXPR_CONTEXT */
|
||||
|
||||
noeval = 0; /* XXX */
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -319,6 +321,7 @@ evalexp (expr, validp)
|
|||
procenv_t oevalbuf;
|
||||
|
||||
val = 0;
|
||||
noeval = 0;
|
||||
|
||||
FASTCOPY (evalbuf, oevalbuf, sizeof (evalbuf));
|
||||
|
||||
|
@ -517,7 +520,8 @@ expcond ()
|
|||
set_noeval = 1;
|
||||
noeval++;
|
||||
}
|
||||
val2 = explor ();
|
||||
|
||||
val2 = expcond ();
|
||||
if (set_noeval)
|
||||
noeval--;
|
||||
rval = cval ? val1 : val2;
|
||||
|
@ -929,6 +933,7 @@ expr_streval (tok, e)
|
|||
if (interactive_shell)
|
||||
{
|
||||
expr_unwind ();
|
||||
top_level_cleanup ();
|
||||
jump_to_top_level (DISCARD);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -308,7 +308,7 @@ search_for_command (pathname)
|
|||
if (hashed_file && (posixly_correct || check_hashed_filenames))
|
||||
{
|
||||
st = file_status (hashed_file);
|
||||
if ((st ^ (FS_EXISTS | FS_EXECABLE)) != 0)
|
||||
if ((st & (FS_EXISTS|FS_EXECABLE)) != (FS_EXISTS|FS_EXECABLE))
|
||||
{
|
||||
phash_remove (pathname);
|
||||
free (hashed_file);
|
||||
|
|
75
jobs.c
75
jobs.c
|
@ -250,6 +250,7 @@ static int job_exit_status __P((int));
|
|||
static int job_exit_signal __P((int));
|
||||
static int set_job_status_and_cleanup __P((int));
|
||||
|
||||
static WAIT job_signal_status __P((int));
|
||||
static WAIT raw_job_exit_status __P((int));
|
||||
|
||||
static void notify_of_job_status __P((void));
|
||||
|
@ -783,11 +784,13 @@ reset_job_indices ()
|
|||
if (jobs[js.j_firstj] == 0)
|
||||
{
|
||||
old = js.j_firstj++;
|
||||
if (old >= js.j_jobslots)
|
||||
old = js.j_jobslots - 1;
|
||||
while (js.j_firstj != old)
|
||||
{
|
||||
if (js.j_firstj >= js.j_jobslots)
|
||||
js.j_firstj = 0;
|
||||
if (jobs[js.j_firstj])
|
||||
if (jobs[js.j_firstj] || js.j_firstj == old) /* needed if old == 0 */
|
||||
break;
|
||||
js.j_firstj++;
|
||||
}
|
||||
|
@ -797,11 +800,13 @@ reset_job_indices ()
|
|||
if (jobs[js.j_lastj] == 0)
|
||||
{
|
||||
old = js.j_lastj--;
|
||||
if (old < 0)
|
||||
old = 0;
|
||||
while (js.j_lastj != old)
|
||||
{
|
||||
if (js.j_lastj < 0)
|
||||
js.j_lastj = js.j_jobslots - 1;
|
||||
if (jobs[js.j_lastj])
|
||||
if (jobs[js.j_lastj] || js.j_lastj == old) /* needed if old == js.j_jobslots */
|
||||
break;
|
||||
js.j_lastj--;
|
||||
}
|
||||
|
@ -963,7 +968,11 @@ compact_jobs_list (flags)
|
|||
reap_dead_jobs ();
|
||||
realloc_jobs_list ();
|
||||
|
||||
return (js.j_lastj);
|
||||
#ifdef DEBUG
|
||||
itrace("compact_jobs_list: returning %d", (js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
|
||||
#endif
|
||||
|
||||
return ((js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
|
||||
}
|
||||
|
||||
/* Delete the job at INDEX from the job list. Must be called
|
||||
|
@ -984,8 +993,6 @@ delete_job (job_index, dflags)
|
|||
temp = jobs[job_index];
|
||||
if (temp == 0)
|
||||
return;
|
||||
if (job_index == js.j_current || job_index == js.j_previous)
|
||||
reset_current ();
|
||||
|
||||
if ((dflags & DEL_NOBGPID) == 0)
|
||||
{
|
||||
|
@ -1028,6 +1035,9 @@ delete_job (job_index, dflags)
|
|||
js.j_firstj = js.j_lastj = 0;
|
||||
else if (jobs[js.j_firstj] == 0 || jobs[js.j_lastj] == 0)
|
||||
reset_job_indices ();
|
||||
|
||||
if (job_index == js.j_current || job_index == js.j_previous)
|
||||
reset_current ();
|
||||
}
|
||||
|
||||
/* Must be called with SIGCHLD blocked. */
|
||||
|
@ -2210,6 +2220,26 @@ process_exit_status (status)
|
|||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
static WAIT
|
||||
job_signal_status (job)
|
||||
int job;
|
||||
{
|
||||
register PROCESS *p;
|
||||
WAIT s;
|
||||
|
||||
p = jobs[job]->pipe;
|
||||
do
|
||||
{
|
||||
s = p->status;
|
||||
if (WIFSIGNALED(s) || WIFSTOPPED(s))
|
||||
break;
|
||||
p = p->next;
|
||||
}
|
||||
while (p != jobs[job]->pipe);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Return the exit status of the last process in the pipeline for job JOB.
|
||||
This is the exit status of the entire job. */
|
||||
static WAIT
|
||||
|
@ -2292,11 +2322,14 @@ wait_for (pid)
|
|||
to finish. We don't want the shell to exit if an interrupt is
|
||||
received, only if one of the jobs run is killed via SIGINT. If
|
||||
job control is not set, the job will be run in the same pgrp as
|
||||
the shell, and the shell will see any signals the job gets. */
|
||||
the shell, and the shell will see any signals the job gets. In
|
||||
fact, we want this set every time the waiting shell and the waited-
|
||||
for process are in the same process group, including command
|
||||
substitution. */
|
||||
|
||||
/* This is possibly a race condition -- should it go in stop_pipeline? */
|
||||
wait_sigint_received = 0;
|
||||
if (job_control == 0)
|
||||
if (job_control == 0 || (subshell_environment&SUBSHELL_COMSUB))
|
||||
{
|
||||
old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
|
||||
if (old_sigint_handler == SIG_IGN)
|
||||
|
@ -2442,15 +2475,7 @@ if (job == NO_JOB)
|
|||
to a signal. We might want to change this later to just check
|
||||
the last process in the pipeline. If no process exits due to a
|
||||
signal, S is left as the status of the last job in the pipeline. */
|
||||
p = jobs[job]->pipe;
|
||||
do
|
||||
{
|
||||
s = p->status;
|
||||
if (WIFSIGNALED(s) || WIFSTOPPED(s))
|
||||
break;
|
||||
p = p->next;
|
||||
}
|
||||
while (p != jobs[job]->pipe);
|
||||
s = job_signal_status (job);
|
||||
|
||||
if (WIFSIGNALED (s) || WIFSTOPPED (s))
|
||||
{
|
||||
|
@ -2484,6 +2509,24 @@ if (job == NO_JOB)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if ((subshell_environment & SUBSHELL_COMSUB) && wait_sigint_received)
|
||||
{
|
||||
/* If waiting for a job in a subshell started to do command
|
||||
substitution, simulate getting and being killed by the SIGINT to
|
||||
pass the status back to our parent. */
|
||||
s = job_signal_status (job);
|
||||
|
||||
if (WIFSIGNALED (s) && WTERMSIG (s) == SIGINT && signal_is_trapped (SIGINT) == 0)
|
||||
{
|
||||
UNBLOCK_CHILD (oset);
|
||||
restore_sigint_handler ();
|
||||
old_sigint_handler = set_signal_handler (SIGINT, SIG_DFL);
|
||||
if (old_sigint_handler == SIG_IGN)
|
||||
restore_sigint_handler ();
|
||||
else
|
||||
kill (getpid (), SIGINT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Moved here from set_job_status_and_cleanup, which is in the SIGCHLD
|
||||
signal handler path */
|
||||
|
|
|
@ -428,7 +428,7 @@ get_y_or_n (for_pager)
|
|||
return (1);
|
||||
if (c == 'n' || c == 'N' || c == RUBOUT)
|
||||
return (0);
|
||||
if (c == ABORT_CHAR)
|
||||
if (c == ABORT_CHAR || c < 0)
|
||||
_rl_abort_internal ();
|
||||
if (for_pager && (c == NEWLINE || c == RETURN))
|
||||
return (2);
|
||||
|
|
|
@ -391,14 +391,14 @@ rl_expand_prompt (prompt)
|
|||
t = ++p;
|
||||
local_prompt = expand_prompt (p, &prompt_visible_length,
|
||||
&prompt_last_invisible,
|
||||
(int *)NULL,
|
||||
&prompt_invis_chars_first_line,
|
||||
&prompt_physical_chars);
|
||||
c = *t; *t = '\0';
|
||||
/* The portion of the prompt string up to and including the
|
||||
final newline is now null-terminated. */
|
||||
local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
|
||||
(int *)NULL,
|
||||
&prompt_invis_chars_first_line,
|
||||
(int *)NULL,
|
||||
(int *)NULL);
|
||||
*t = c;
|
||||
local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
|
||||
|
@ -561,6 +561,17 @@ rl_redisplay ()
|
|||
wrap_offset = prompt_invis_chars_first_line = 0;
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
#define CHECK_INV_LBREAKS() \
|
||||
do { \
|
||||
if (newlines >= (inv_lbsize - 2)) \
|
||||
{ \
|
||||
inv_lbsize *= 2; \
|
||||
inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
|
||||
_rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define CHECK_INV_LBREAKS() \
|
||||
do { \
|
||||
if (newlines >= (inv_lbsize - 2)) \
|
||||
|
@ -569,6 +580,7 @@ rl_redisplay ()
|
|||
inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
#define CHECK_LPOS() \
|
||||
|
@ -898,6 +910,10 @@ rl_redisplay ()
|
|||
second and subsequent lines start at inv_lbreaks[N], offset by
|
||||
OFFSET (which has already been calculated above). */
|
||||
|
||||
#define INVIS_FIRST() (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
|
||||
#define WRAP_OFFSET(line, offset) ((line == 0) \
|
||||
? (offset ? INVIS_FIRST() : 0) \
|
||||
: ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
|
||||
#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
|
||||
#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
|
||||
#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
|
||||
|
@ -932,7 +948,13 @@ rl_redisplay ()
|
|||
_rl_last_c_pos != o_cpos &&
|
||||
_rl_last_c_pos > wrap_offset &&
|
||||
o_cpos < prompt_last_invisible)
|
||||
_rl_last_c_pos -= wrap_offset;
|
||||
_rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
|
||||
else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth &&
|
||||
(MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
|
||||
cpos_adjusted == 0 &&
|
||||
_rl_last_c_pos != o_cpos &&
|
||||
_rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))
|
||||
_rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
|
||||
|
||||
/* If this is the line with the prompt, we might need to
|
||||
compensate for invisible characters in the new line. Do
|
||||
|
@ -1036,7 +1058,7 @@ rl_redisplay ()
|
|||
tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset;
|
||||
else
|
||||
tx = nleft;
|
||||
if (_rl_last_c_pos > tx)
|
||||
if (tx >= 0 && _rl_last_c_pos > tx)
|
||||
{
|
||||
_rl_backspace (_rl_last_c_pos - tx); /* XXX */
|
||||
_rl_last_c_pos = tx;
|
||||
|
@ -1192,7 +1214,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
int current_line, omax, nmax, inv_botlin;
|
||||
{
|
||||
register char *ofd, *ols, *oe, *nfd, *nls, *ne;
|
||||
int temp, lendiff, wsatend, od, nd;
|
||||
int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
|
||||
int current_invis_chars;
|
||||
int col_lendiff, col_temp;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
|
@ -1208,7 +1230,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
temp = _rl_last_c_pos;
|
||||
else
|
||||
temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
|
||||
temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
|
||||
if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
|
||||
&& _rl_last_v_pos == current_line - 1)
|
||||
{
|
||||
|
@ -1453,6 +1475,8 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
_rl_last_c_pos = lendiff;
|
||||
}
|
||||
|
||||
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
|
||||
multibyte locale. */
|
||||
|
@ -1462,7 +1486,9 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
/* 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
|
||||
we make sure we're at the end of the drawn prompt string works. */
|
||||
if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_last_c_pos == prompt_physical_chars)
|
||||
if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 &&
|
||||
(_rl_last_c_pos > 0 || o_cpos > 0) &&
|
||||
_rl_last_c_pos == prompt_physical_chars)
|
||||
cpos_adjusted = 1;
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1506,11 +1532,31 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
{
|
||||
/* Non-zero if we're increasing the number of lines. */
|
||||
int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
|
||||
/* If col_lendiff is > 0, implying that the new string takes up more
|
||||
screen real estate than the old, but lendiff is < 0, meaning that it
|
||||
takes fewer bytes, we need to just output the characters starting
|
||||
from the first difference. These will overwrite what is on the
|
||||
display, so there's no reason to do a smart update. This can really
|
||||
only happen in a multibyte environment. */
|
||||
if (lendiff < 0)
|
||||
{
|
||||
_rl_output_some_chars (nfd, temp);
|
||||
_rl_last_c_pos += _rl_col_width (nfd, 0, temp);
|
||||
/* 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))
|
||||
{
|
||||
_rl_last_c_pos -= wrap_offset;
|
||||
cpos_adjusted = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* Sometimes it is cheaper to print the characters rather than
|
||||
use the terminal's capabilities. If we're growing the number
|
||||
of lines, make sure we actually cause the new line to wrap
|
||||
around on auto-wrapping terminals. */
|
||||
if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
|
||||
else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
|
||||
{
|
||||
/* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
|
||||
_rl_horizontal_scroll_mode == 1, inserting the characters with
|
||||
|
@ -1533,11 +1579,16 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* We have horizontal scrolling and we are not inserting at
|
||||
the end. We have invisible characters in this line. This
|
||||
is a dumb update. */
|
||||
_rl_output_some_chars (nfd, temp);
|
||||
_rl_last_c_pos += col_temp;
|
||||
/* 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))
|
||||
{
|
||||
_rl_last_c_pos -= wrap_offset;
|
||||
cpos_adjusted = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* Copy (new) chars to screen from first diff to last match. */
|
||||
|
@ -1545,15 +1596,15 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
if ((temp - lendiff) > 0)
|
||||
{
|
||||
_rl_output_some_chars (nfd + lendiff, temp - lendiff);
|
||||
#if 1
|
||||
/* 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. */
|
||||
_rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
|
||||
#else
|
||||
_rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff);
|
||||
#endif
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
twidth = _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
|
||||
else
|
||||
twidth = temp - lendiff;
|
||||
_rl_last_c_pos += twidth;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1586,8 +1637,22 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
temp = nls - nfd;
|
||||
if (temp > 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_last_c_pos += _rl_col_width (nfd, 0, temp);;
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
_rl_last_c_pos += _rl_col_width (nfd, 0, temp);
|
||||
if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
|
||||
{
|
||||
_rl_last_c_pos -= wrap_offset;
|
||||
cpos_adjusted = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
_rl_last_c_pos += temp;
|
||||
}
|
||||
}
|
||||
/* Otherwise, print over the existing material. */
|
||||
|
@ -1595,8 +1660,20 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
|||
{
|
||||
if (temp > 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_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))
|
||||
{
|
||||
_rl_last_c_pos -= wrap_offset;
|
||||
cpos_adjusted = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
lendiff = (oe - old) - (ne - new);
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
|
@ -1721,7 +1798,7 @@ _rl_move_cursor_relative (new, data)
|
|||
int woff; /* number of invisible chars on current line */
|
||||
int cpos, dpos; /* current and desired cursor positions */
|
||||
|
||||
woff = W_OFFSET (_rl_last_v_pos, wrap_offset);
|
||||
woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
|
||||
cpos = _rl_last_c_pos;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* If we have multibyte characters, NEW is indexed by the buffer point in
|
||||
|
@ -1732,7 +1809,14 @@ _rl_move_cursor_relative (new, data)
|
|||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
dpos = _rl_col_width (data, 0, new);
|
||||
if (dpos > prompt_last_invisible) /* XXX - don't use woff here */
|
||||
/* 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. */
|
||||
if ((new > prompt_last_invisible) || /* XXX - don't use woff here */
|
||||
(prompt_physical_chars > _rl_screenwidth &&
|
||||
_rl_last_v_pos == prompt_last_screen_line &&
|
||||
wrap_offset != woff &&
|
||||
new > (prompt_last_invisible-_rl_screenwidth-wrap_offset)))
|
||||
{
|
||||
dpos -= woff;
|
||||
/* Since this will be assigned to _rl_last_c_pos at the end (more
|
||||
|
@ -2380,6 +2464,8 @@ _rl_col_width (str, start, end)
|
|||
|
||||
if (end <= start)
|
||||
return 0;
|
||||
if (MB_CUR_MAX == 1 || rl_byte_oriented)
|
||||
return (end - start);
|
||||
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
|
||||
|
|
|
@ -133,8 +133,11 @@ rl_get_char (key)
|
|||
return (0);
|
||||
|
||||
*key = ibuffer[pop_index++];
|
||||
|
||||
#if 0
|
||||
if (pop_index >= ibuffer_len)
|
||||
#else
|
||||
if (pop_index > ibuffer_len)
|
||||
#endif
|
||||
pop_index = 0;
|
||||
|
||||
return (1);
|
||||
|
@ -151,7 +154,7 @@ _rl_unget_char (key)
|
|||
{
|
||||
pop_index--;
|
||||
if (pop_index < 0)
|
||||
pop_index = ibuffer_len - 1;
|
||||
pop_index = ibuffer_len;
|
||||
ibuffer[pop_index] = key;
|
||||
return (1);
|
||||
}
|
||||
|
@ -250,7 +253,8 @@ rl_gather_tyi ()
|
|||
while (chars_avail--)
|
||||
{
|
||||
k = (*rl_getc_function) (rl_instream);
|
||||
rl_stuff_char (k);
|
||||
if (rl_stuff_char (k) == 0)
|
||||
break; /* some problem; no more room */
|
||||
if (k == NEWLINE || k == RETURN)
|
||||
break;
|
||||
}
|
||||
|
@ -373,7 +377,11 @@ rl_stuff_char (key)
|
|||
RL_SETSTATE (RL_STATE_INPUTPENDING);
|
||||
}
|
||||
ibuffer[push_index++] = key;
|
||||
#if 0
|
||||
if (push_index >= ibuffer_len)
|
||||
#else
|
||||
if (push_index > ibuffer_len)
|
||||
#endif
|
||||
push_index = 0;
|
||||
|
||||
return 1;
|
||||
|
@ -513,20 +521,26 @@ _rl_read_mbchar (mbchar, size)
|
|||
char *mbchar;
|
||||
int size;
|
||||
{
|
||||
int mb_len = 0;
|
||||
int mb_len, c;
|
||||
size_t mbchar_bytes_length;
|
||||
wchar_t wc;
|
||||
mbstate_t ps, ps_back;
|
||||
|
||||
memset(&ps, 0, sizeof (mbstate_t));
|
||||
memset(&ps_back, 0, sizeof (mbstate_t));
|
||||
|
||||
|
||||
mb_len = 0;
|
||||
while (mb_len < size)
|
||||
{
|
||||
RL_SETSTATE(RL_STATE_MOREINPUT);
|
||||
mbchar[mb_len++] = rl_read_key ();
|
||||
c = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
|
||||
if (c < 0)
|
||||
break;
|
||||
|
||||
mbchar[mb_len++] = c;
|
||||
|
||||
mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps);
|
||||
if (mbchar_bytes_length == (size_t)(-1))
|
||||
break; /* invalid byte sequence for the current locale */
|
||||
|
@ -564,7 +578,7 @@ _rl_read_mbstring (first, mb, mlen)
|
|||
|
||||
c = first;
|
||||
memset (mb, 0, mlen);
|
||||
for (i = 0; i < mlen; i++)
|
||||
for (i = 0; c >= 0 && i < mlen; i++)
|
||||
{
|
||||
mb[i] = (char)c;
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
|
|
|
@ -327,8 +327,15 @@ _rl_isearch_dispatch (cxt, c)
|
|||
rl_command_func_t *f;
|
||||
|
||||
f = (rl_command_func_t *)NULL;
|
||||
|
||||
/* Translate the keys we do something with to opcodes. */
|
||||
|
||||
if (c < 0)
|
||||
{
|
||||
cxt->sflags |= SF_FAILED;
|
||||
cxt->history_pos = cxt->last_found_line;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Translate the keys we do something with to opcodes. */
|
||||
if (c >= 0 && _rl_keymap[c].type == ISFUNC)
|
||||
{
|
||||
f = _rl_keymap[c].function;
|
||||
|
|
|
@ -146,6 +146,8 @@ _rl_arg_dispatch (cxt, c)
|
|||
rl_restore_prompt ();
|
||||
rl_clear_message ();
|
||||
RL_UNSETSTATE(RL_STATE_NUMERICARG);
|
||||
if (key < 0)
|
||||
return -1;
|
||||
return (_rl_dispatch (key, _rl_keymap));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -645,6 +645,11 @@ _rl_dispatch_callback (cxt)
|
|||
if ((cxt->flags & KSEQ_DISPATCHED) == 0)
|
||||
{
|
||||
nkey = _rl_subseq_getchar (cxt->okey);
|
||||
if (nkey < 0)
|
||||
{
|
||||
_rl_abort_internal ();
|
||||
return -1;
|
||||
}
|
||||
r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg);
|
||||
cxt->flags |= KSEQ_DISPATCHED;
|
||||
}
|
||||
|
|
|
@ -857,6 +857,9 @@ _rl_insert_next (count)
|
|||
c = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
|
||||
_rl_restore_tty_signals ();
|
||||
|
@ -1520,6 +1523,9 @@ _rl_char_search (count, fdir, bdir)
|
|||
|
||||
mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
|
||||
|
||||
if (mb_len <= 0)
|
||||
return -1;
|
||||
|
||||
if (count < 0)
|
||||
return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
|
||||
else
|
||||
|
@ -1536,6 +1542,9 @@ _rl_char_search (count, fdir, bdir)
|
|||
c = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
if (count < 0)
|
||||
return (_rl_char_search_internal (-count, bdir, c));
|
||||
else
|
||||
|
|
|
@ -886,6 +886,13 @@ rl_vi_domove (key, nextkey)
|
|||
RL_SETSTATE(RL_STATE_MOREINPUT);
|
||||
c = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
|
||||
if (c < 0)
|
||||
{
|
||||
*nextkey = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*nextkey = c;
|
||||
|
||||
if (!member (c, vi_motion))
|
||||
|
@ -902,6 +909,11 @@ rl_vi_domove (key, nextkey)
|
|||
RL_SETSTATE(RL_STATE_MOREINPUT);
|
||||
c = rl_read_key (); /* real command */
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
if (c < 0)
|
||||
{
|
||||
*nextkey = 0;
|
||||
return -1;
|
||||
}
|
||||
*nextkey = c;
|
||||
}
|
||||
else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
|
||||
|
@ -1224,14 +1236,22 @@ static int
|
|||
_rl_vi_callback_char_search (data)
|
||||
_rl_callback_generic_arg *data;
|
||||
{
|
||||
int c;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
_rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
|
||||
c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
|
||||
#else
|
||||
RL_SETSTATE(RL_STATE_MOREINPUT);
|
||||
_rl_vi_last_search_char = rl_read_key ();
|
||||
c = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
#endif
|
||||
|
||||
if (c <= 0)
|
||||
return -1;
|
||||
|
||||
#if !defined (HANDLE_MULTIBYTE)
|
||||
_rl_vi_last_search_char = c;
|
||||
#endif
|
||||
|
||||
_rl_callback_func = 0;
|
||||
_rl_want_redisplay = 1;
|
||||
|
||||
|
@ -1247,6 +1267,7 @@ int
|
|||
rl_vi_char_search (count, key)
|
||||
int count, key;
|
||||
{
|
||||
int c;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
static char *target;
|
||||
static int tlen;
|
||||
|
@ -1293,11 +1314,17 @@ rl_vi_char_search (count, key)
|
|||
else
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
_rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
|
||||
c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
|
||||
if (c <= 0)
|
||||
return -1;
|
||||
_rl_vi_last_search_mblen = c;
|
||||
#else
|
||||
RL_SETSTATE(RL_STATE_MOREINPUT);
|
||||
_rl_vi_last_search_char = rl_read_key ();
|
||||
c = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
if (c < 0)
|
||||
return -1;
|
||||
_rl_vi_last_search_char = c;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1467,6 +1494,9 @@ _rl_vi_callback_getchar (mb, mlen)
|
|||
c = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
c = _rl_read_mbstring (c, mb, mlen);
|
||||
|
@ -1485,6 +1515,9 @@ _rl_vi_callback_change_char (data)
|
|||
|
||||
_rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
|
||||
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
_rl_callback_func = 0;
|
||||
_rl_want_redisplay = 1;
|
||||
|
||||
|
@ -1516,6 +1549,9 @@ rl_vi_change_char (count, key)
|
|||
else
|
||||
_rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
|
||||
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
return (_rl_vi_change_char (count, c, mb));
|
||||
}
|
||||
|
||||
|
@ -1650,7 +1686,7 @@ _rl_vi_set_mark ()
|
|||
ch = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
|
||||
if (ch < 'a' || ch > 'z')
|
||||
if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
|
||||
{
|
||||
rl_ding ();
|
||||
return -1;
|
||||
|
@ -1702,7 +1738,7 @@ _rl_vi_goto_mark ()
|
|||
rl_point = rl_mark;
|
||||
return 0;
|
||||
}
|
||||
else if (ch < 'a' || ch > 'z')
|
||||
else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
|
||||
{
|
||||
rl_ding ();
|
||||
return -1;
|
||||
|
|
|
@ -251,19 +251,21 @@ getcwd (buf, size)
|
|||
|
||||
{
|
||||
size_t len = pathbuf + pathsize - pathp;
|
||||
if (buf == NULL)
|
||||
{
|
||||
if (len < (size_t) size)
|
||||
len = size;
|
||||
buf = (char *) malloc (len);
|
||||
if (buf == NULL)
|
||||
goto lose2;
|
||||
}
|
||||
else if ((size_t) size < len)
|
||||
if (buf == NULL && size <= 0)
|
||||
size = len;
|
||||
|
||||
if ((size_t) size < len)
|
||||
{
|
||||
errno = ERANGE;
|
||||
goto lose2;
|
||||
}
|
||||
if (buf == NULL)
|
||||
{
|
||||
buf = (char *) malloc (size);
|
||||
if (buf == NULL)
|
||||
goto lose2;
|
||||
}
|
||||
|
||||
(void) memcpy((PTR_T) buf, (PTR_T) pathp, len);
|
||||
}
|
||||
|
||||
|
|
|
@ -471,6 +471,8 @@ pow_10(n)
|
|||
10^x ~= r
|
||||
* log_10(200) = 2;
|
||||
* log_10(250) = 2;
|
||||
*
|
||||
* NOTE: do not call this with r == 0 -- an infinite loop results.
|
||||
*/
|
||||
static int
|
||||
log_10(r)
|
||||
|
@ -576,8 +578,11 @@ numtoa(number, base, precision, fract)
|
|||
{
|
||||
integral_part[0] = '0';
|
||||
integral_part[1] = '\0';
|
||||
fraction_part[0] = '0';
|
||||
fraction_part[1] = '\0';
|
||||
/* The fractional part has to take the precision into account */
|
||||
for (ch = 0; ch < precision-1; ch++)
|
||||
fraction_part[ch] = '0';
|
||||
fraction_part[ch] = '0';
|
||||
fraction_part[ch+1] = '\0';
|
||||
if (fract)
|
||||
*fract = fraction_part;
|
||||
return integral_part;
|
||||
|
@ -663,7 +668,8 @@ number(p, d, base)
|
|||
p->flags &= ~PF_ZEROPAD;
|
||||
|
||||
sd = d; /* signed for ' ' padding in base 10 */
|
||||
flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
|
||||
flags = 0;
|
||||
flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
|
||||
if (*p->pf == 'X')
|
||||
flags |= FL_HEXUPPER;
|
||||
|
||||
|
@ -733,7 +739,7 @@ lnumber(p, d, base)
|
|||
p->flags &= ~PF_ZEROPAD;
|
||||
|
||||
sd = d; /* signed for ' ' padding in base 10 */
|
||||
flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
|
||||
flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
|
||||
if (*p->pf == 'X')
|
||||
flags |= FL_HEXUPPER;
|
||||
|
||||
|
@ -805,6 +811,7 @@ pointer(p, d)
|
|||
PUT_CHAR(*tmp, p);
|
||||
tmp++;
|
||||
}
|
||||
|
||||
PAD_LEFT(p);
|
||||
}
|
||||
|
||||
|
@ -972,11 +979,21 @@ floating(p, d)
|
|||
if ((p->flags & PF_THOUSANDS) && grouping && (t = groupnum (tmp)))
|
||||
tmp = t;
|
||||
|
||||
if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
|
||||
{
|
||||
/* smash the trailing zeros unless altform */
|
||||
for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
|
||||
tmp2[i] = '\0';
|
||||
if (tmp2[0] == '\0')
|
||||
p->precision = 0;
|
||||
}
|
||||
|
||||
/* calculate the padding. 1 for the dot */
|
||||
p->width = p->width -
|
||||
((d > 0. && p->justify == RIGHT) ? 1:0) -
|
||||
((p->flags & PF_SPACE) ? 1:0) -
|
||||
strlen(tmp) - p->precision - 1;
|
||||
strlen(tmp) - p->precision -
|
||||
((p->precision != 0 || (p->flags & PF_ALTFORM)) ? 1 : 0); /* radix char */
|
||||
PAD_RIGHT(p);
|
||||
PUT_PLUS(d, p, 0.);
|
||||
PUT_SPACE(d, p, 0.);
|
||||
|
@ -991,11 +1008,6 @@ floating(p, d)
|
|||
if (p->precision != 0 || (p->flags & PF_ALTFORM))
|
||||
PUT_CHAR(decpoint, p); /* put the '.' */
|
||||
|
||||
if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
|
||||
/* smash the trailing zeros unless altform */
|
||||
for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
|
||||
tmp2[i] = '\0';
|
||||
|
||||
for (; *tmp2; tmp2++)
|
||||
PUT_CHAR(*tmp2, p); /* the fraction */
|
||||
|
||||
|
@ -1011,14 +1023,19 @@ exponent(p, d)
|
|||
char *tmp, *tmp2;
|
||||
int j, i;
|
||||
|
||||
if (chkinfnan(p, d, 1) || chkinfnan(p, d, 2))
|
||||
if (d != 0 && (chkinfnan(p, d, 1) || chkinfnan(p, d, 2)))
|
||||
return; /* already printed nan or inf */
|
||||
|
||||
GETLOCALEDATA(decpoint, thoussep, grouping);
|
||||
DEF_PREC(p);
|
||||
j = log_10(d);
|
||||
d = d / pow_10(j); /* get the Mantissa */
|
||||
d = ROUND(d, p);
|
||||
if (d == 0.)
|
||||
j = 0;
|
||||
else
|
||||
{
|
||||
j = log_10(d);
|
||||
d = d / pow_10(j); /* get the Mantissa */
|
||||
d = ROUND(d, p);
|
||||
}
|
||||
tmp = dtoa(d, p->precision, &tmp2);
|
||||
|
||||
/* 1 for unit, 1 for the '.', 1 for 'e|E',
|
||||
|
@ -1076,6 +1093,7 @@ exponent(p, d)
|
|||
PUT_CHAR(*tmp, p);
|
||||
tmp++;
|
||||
}
|
||||
|
||||
PAD_LEFT(p);
|
||||
}
|
||||
#endif
|
||||
|
@ -1358,7 +1376,7 @@ conv_break:
|
|||
STAR_ARGS(data);
|
||||
DEF_PREC(data);
|
||||
d = GETDOUBLE(data);
|
||||
i = log_10(d);
|
||||
i = (d != 0.) ? log_10(d) : -1;
|
||||
/*
|
||||
* for '%g|%G' ANSI: use f if exponent
|
||||
* is in the range or [-4,p] exclusively
|
||||
|
|
54
parse.y
54
parse.y
|
@ -1029,6 +1029,7 @@ timespec: TIME
|
|||
#define PST_CMDTOKEN 0x1000 /* command token OK - unused */
|
||||
#define PST_COMPASSIGN 0x2000 /* parsing x=(...) compound assignment */
|
||||
#define PST_ASSIGNOK 0x4000 /* assignment statement ok in this context */
|
||||
#define PST_REGEXP 0x8000 /* parsing an ERE/BRE as a single word */
|
||||
|
||||
/* Initial size to allocate for tokens, and the
|
||||
amount to grow them by. */
|
||||
|
@ -2591,6 +2592,9 @@ read_token (command)
|
|||
return (character);
|
||||
}
|
||||
|
||||
if (parser_state & PST_REGEXP)
|
||||
goto tokword;
|
||||
|
||||
/* Shell meta-characters. */
|
||||
if MBTEST(shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0))
|
||||
{
|
||||
|
@ -2698,6 +2702,7 @@ read_token (command)
|
|||
if MBTEST(character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND))
|
||||
return (character);
|
||||
|
||||
tokword:
|
||||
/* Okay, if we got this far, we have to read a word. Read one,
|
||||
and then check it against the known ones. */
|
||||
result = read_token_word (character);
|
||||
|
@ -2735,7 +2740,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
|||
/* itrace("parse_matched_pair: open = %c close = %c", open, close); */
|
||||
count = 1;
|
||||
pass_next_character = backq_backslash = was_dollar = in_comment = 0;
|
||||
check_comment = (flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0;
|
||||
check_comment = (flags & P_COMMAND) && qc != '`' && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0;
|
||||
|
||||
/* RFLAGS is the set of flags we want to pass to recursive calls. */
|
||||
rflags = (qc == '"') ? P_DQUOTE : (flags & P_DQUOTE);
|
||||
|
@ -3202,8 +3207,11 @@ cond_term ()
|
|||
if (tok == WORD && test_binop (yylval.word->word))
|
||||
op = yylval.word;
|
||||
#if defined (COND_REGEXP)
|
||||
else if (tok == WORD && STREQ (yylval.word->word,"=~"))
|
||||
op = yylval.word;
|
||||
else if (tok == WORD && STREQ (yylval.word->word, "=~"))
|
||||
{
|
||||
op = yylval.word;
|
||||
parser_state |= PST_REGEXP;
|
||||
}
|
||||
#endif
|
||||
else if (tok == '<' || tok == '>')
|
||||
op = make_word_from_token (tok); /* ( */
|
||||
|
@ -3234,6 +3242,7 @@ cond_term ()
|
|||
|
||||
/* rhs */
|
||||
tok = read_token (READ);
|
||||
parser_state &= ~PST_REGEXP;
|
||||
if (tok == WORD)
|
||||
{
|
||||
tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
|
||||
|
@ -3367,7 +3376,7 @@ read_token_word (character)
|
|||
if (pass_next_character)
|
||||
{
|
||||
pass_next_character = 0;
|
||||
goto got_character;
|
||||
goto got_escaped_character;
|
||||
}
|
||||
|
||||
cd = current_delimiter (dstack);
|
||||
|
@ -3419,9 +3428,34 @@ read_token_word (character)
|
|||
goto next_character;
|
||||
}
|
||||
|
||||
#ifdef COND_REGEXP
|
||||
/* When parsing a regexp as a single word inside a conditional command,
|
||||
we need to special-case characters special to both the shell and
|
||||
regular expressions. Right now, that is only '(' and '|'. */ /*)*/
|
||||
if MBTEST((parser_state & PST_REGEXP) && (character == '(' || character == '|')) /*)*/
|
||||
{
|
||||
if (character == '|')
|
||||
goto got_character;
|
||||
|
||||
push_delimiter (dstack, character);
|
||||
ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
|
||||
pop_delimiter (dstack);
|
||||
if (ttok == &matched_pair_error)
|
||||
return -1; /* Bail immediately. */
|
||||
RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
|
||||
token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
|
||||
token[token_index++] = character;
|
||||
strcpy (token + token_index, ttok);
|
||||
token_index += ttoklen;
|
||||
FREE (ttok);
|
||||
dollar_present = all_digit_token = 0;
|
||||
goto next_character;
|
||||
}
|
||||
#endif /* COND_REGEXP */
|
||||
|
||||
#ifdef EXTENDED_GLOB
|
||||
/* Parse a ksh-style extended pattern matching specification. */
|
||||
if (extended_glob && PATTERN_CHAR (character))
|
||||
if MBTEST(extended_glob && PATTERN_CHAR (character))
|
||||
{
|
||||
peek_char = shell_getc (1);
|
||||
if MBTEST(peek_char == '(') /* ) */
|
||||
|
@ -3616,12 +3650,14 @@ read_token_word (character)
|
|||
|
||||
got_character:
|
||||
|
||||
all_digit_token &= DIGIT (character);
|
||||
dollar_present |= character == '$';
|
||||
|
||||
if (character == CTLESC || character == CTLNUL)
|
||||
token[token_index++] = CTLESC;
|
||||
|
||||
got_escaped_character:
|
||||
|
||||
all_digit_token &= DIGIT (character);
|
||||
dollar_present |= character == '$';
|
||||
|
||||
token[token_index++] = character;
|
||||
|
||||
RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size,
|
||||
|
@ -4330,7 +4366,7 @@ not_escape:
|
|||
if (promptvars || posixly_correct)
|
||||
{
|
||||
last_exit_value = last_command_exit_value;
|
||||
list = expand_prompt_string (result, Q_DOUBLE_QUOTES);
|
||||
list = expand_prompt_string (result, Q_DOUBLE_QUOTES, 0);
|
||||
free (result);
|
||||
result = string_list (list);
|
||||
dispose_words (list);
|
||||
|
|
|
@ -25,6 +25,6 @@
|
|||
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
|
||||
looks for to find the patch level (for the sccs version string). */
|
||||
|
||||
#define PATCHLEVEL 0
|
||||
#define PATCHLEVEL 48
|
||||
|
||||
#endif /* _PATCHLEVEL_H_ */
|
||||
|
|
31
pathexp.c
31
pathexp.c
|
@ -1,6 +1,6 @@
|
|||
/* pathexp.c -- The shell interface to the globbing library. */
|
||||
|
||||
/* Copyright (C) 1995-2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -110,6 +110,33 @@ unquoted_glob_pattern_p (string)
|
|||
return (0);
|
||||
}
|
||||
|
||||
/* Return 1 if C is a character that is `special' in a POSIX ERE and needs to
|
||||
be quoted to match itself. */
|
||||
static inline int
|
||||
ere_char (c)
|
||||
int c;
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '.':
|
||||
case '[':
|
||||
case '\\':
|
||||
case '(':
|
||||
case ')':
|
||||
case '*':
|
||||
case '+':
|
||||
case '?':
|
||||
case '{':
|
||||
case '|':
|
||||
case '^':
|
||||
case '$':
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* PATHNAME can contain characters prefixed by CTLESC; this indicates
|
||||
that the character is to be quoted. We quote it here in the style
|
||||
that the glob library recognizes. If flags includes QGLOB_CVTNULL,
|
||||
|
@ -142,6 +169,8 @@ quote_string_for_globbing (pathname, qflags)
|
|||
{
|
||||
if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
|
||||
continue;
|
||||
if ((qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
|
||||
continue;
|
||||
temp[j++] = '\\';
|
||||
i++;
|
||||
if (pathname[i] == '\0')
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pathexp.h -- The shell interface to the globbing library. */
|
||||
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -32,6 +32,7 @@ extern char *glob_error_return;
|
|||
/* Flag values for quote_string_for_globbing */
|
||||
#define QGLOB_CVTNULL 0x01 /* convert QUOTED_NULL strings to '\0' */
|
||||
#define QGLOB_FILENAME 0x02 /* do correct quoting for matching filenames */
|
||||
#define QGLOB_REGEXP 0x04 /* quote an ERE for regcomp/regexec */
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
/* Flags to OR with other flag args to strmatch() to enabled the extended
|
||||
|
|
BIN
po/ru.gmo
Normal file
BIN
po/ru.gmo
Normal file
Binary file not shown.
2
po/ru.po
2
po/ru.po
|
@ -12,7 +12,7 @@ msgstr ""
|
|||
"Last-Translator: Evgeniy Dushistov <dushistov@mail.ru>\n"
|
||||
"Language-Team: Russian <ru@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Type: text/plain; charset=KOI8-R\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
|
|
1
shell.h
1
shell.h
|
@ -89,6 +89,7 @@ extern int debugging_mode;
|
|||
extern int executing, login_shell;
|
||||
extern int interactive, interactive_shell;
|
||||
extern int startup_state;
|
||||
extern int shell_compatibility_level;
|
||||
|
||||
/* Structure to pass around that holds a bitmap of file descriptors
|
||||
to close, and the size of that structure. Used in execute_cmd.c. */
|
||||
|
|
19
sig.c
19
sig.c
|
@ -350,6 +350,25 @@ reset_terminating_signals ()
|
|||
#undef XSIG
|
||||
#undef XHANDLER
|
||||
|
||||
/* Run some of the cleanups that should be performed when we run
|
||||
jump_to_top_level from a builtin command context. XXX - might want to
|
||||
also call reset_parser here. */
|
||||
void
|
||||
top_level_cleanup ()
|
||||
{
|
||||
/* Clean up string parser environment. */
|
||||
while (parse_and_execute_level)
|
||||
parse_and_execute_cleanup ();
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
unlink_fifo_list ();
|
||||
#endif /* PROCESS_SUBSTITUTION */
|
||||
|
||||
run_unwind_protects ();
|
||||
loop_level = continuing = breaking = 0;
|
||||
return_catch_flag = 0;
|
||||
}
|
||||
|
||||
/* What to do when we've been interrupted, and it is safe to handle it. */
|
||||
void
|
||||
throw_to_top_level ()
|
||||
|
|
1
sig.h
1
sig.h
|
@ -121,6 +121,7 @@ extern sighandler sigint_sighandler __P((int));
|
|||
extern void initialize_signals __P((int));
|
||||
extern void initialize_terminating_signals __P((void));
|
||||
extern void reset_terminating_signals __P((void));
|
||||
extern void top_level_cleanup __P((void));
|
||||
extern void throw_to_top_level __P((void));
|
||||
extern void jump_to_top_level __P((int)) __attribute__((__noreturn__));
|
||||
|
||||
|
|
119
subst.c
119
subst.c
|
@ -4,7 +4,7 @@
|
|||
/* ``Have a little faith, there's magic in the night. You ain't a
|
||||
beauty, but, hey, you're alright.'' */
|
||||
|
||||
/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -137,7 +137,7 @@ unsigned char ifs_firstc;
|
|||
/* Extern functions and variables from different files. */
|
||||
extern int last_command_exit_value, last_command_exit_signal;
|
||||
extern int subshell_environment;
|
||||
extern int subshell_level;
|
||||
extern int subshell_level, parse_and_execute_level;
|
||||
extern int eof_encountered;
|
||||
extern int return_catch_flag, return_catch_value;
|
||||
extern pid_t dollar_dollar_pid;
|
||||
|
@ -1278,7 +1278,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
|||
{
|
||||
if (no_longjmp_on_fatal_error == 0)
|
||||
{ /* { */
|
||||
report_error ("bad substitution: no closing `%s' in %s", "}", string);
|
||||
report_error (_("bad substitution: no closing `%s' in %s"), "}", string);
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
exp_jump_to_top_level (DISCARD);
|
||||
}
|
||||
|
@ -1887,7 +1887,13 @@ string_list_dollar_at (list, quoted)
|
|||
sep[1] = '\0';
|
||||
#endif
|
||||
|
||||
/* XXX -- why call quote_list if ifs == 0? we can get away without doing
|
||||
it now that quote_escapes quotes spaces */
|
||||
#if 0
|
||||
tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
|
||||
#else
|
||||
tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
|
||||
#endif
|
||||
? quote_list (list)
|
||||
: list_quote_escapes (list);
|
||||
|
||||
|
@ -2646,11 +2652,12 @@ remove_backslashes (string)
|
|||
|
||||
/* This needs better error handling. */
|
||||
/* Expand W for use as an argument to a unary or binary operator in a
|
||||
[[...]] expression. If SPECIAL is nonzero, this is the rhs argument
|
||||
[[...]] expression. If SPECIAL is 1, this is the rhs argument
|
||||
to the != or == operator, and should be treated as a pattern. In
|
||||
this case, we quote the string specially for the globbing code. The
|
||||
caller is responsible for removing the backslashes if the unquoted
|
||||
words is needed later. */
|
||||
this case, we quote the string specially for the globbing code. If
|
||||
SPECIAL is 2, this is an rhs argument for the =~ operator, and should
|
||||
be quoted appropriately for regcomp/regexec. The caller is responsible
|
||||
for removing the backslashes if the unquoted word is needed later. */
|
||||
char *
|
||||
cond_expand_word (w, special)
|
||||
WORD_DESC *w;
|
||||
|
@ -2658,6 +2665,7 @@ cond_expand_word (w, special)
|
|||
{
|
||||
char *r, *p;
|
||||
WORD_LIST *l;
|
||||
int qflags;
|
||||
|
||||
if (w->word == 0 || w->word[0] == '\0')
|
||||
return ((char *)NULL);
|
||||
|
@ -2672,8 +2680,11 @@ cond_expand_word (w, special)
|
|||
}
|
||||
else
|
||||
{
|
||||
qflags = QGLOB_CVTNULL;
|
||||
if (special == 2)
|
||||
qflags |= QGLOB_REGEXP;
|
||||
p = string_list (l);
|
||||
r = quote_string_for_globbing (p, QGLOB_CVTNULL);
|
||||
r = quote_string_for_globbing (p, qflags);
|
||||
free (p);
|
||||
}
|
||||
dispose_words (l);
|
||||
|
@ -2803,9 +2814,10 @@ expand_string_assignment (string, quoted)
|
|||
passed string when an error occurs. Might want to trap other calls
|
||||
to jump_to_top_level here so we don't endlessly loop. */
|
||||
WORD_LIST *
|
||||
expand_prompt_string (string, quoted)
|
||||
expand_prompt_string (string, quoted, wflags)
|
||||
char *string;
|
||||
int quoted;
|
||||
int wflags;
|
||||
{
|
||||
WORD_LIST *value;
|
||||
WORD_DESC td;
|
||||
|
@ -2813,7 +2825,7 @@ expand_prompt_string (string, quoted)
|
|||
if (string == 0 || *string == 0)
|
||||
return ((WORD_LIST *)NULL);
|
||||
|
||||
td.flags = 0;
|
||||
td.flags = wflags;
|
||||
td.word = savestring (string);
|
||||
|
||||
no_longjmp_on_fatal_error = 1;
|
||||
|
@ -2916,7 +2928,12 @@ expand_string (string, quoted)
|
|||
|
||||
/* Quote escape characters in string s, but no other characters. This is
|
||||
used to protect CTLESC and CTLNUL in variable values from the rest of
|
||||
the word expansion process after the variable is expanded. */
|
||||
the word expansion process after the variable is expanded. If IFS is
|
||||
null, we quote spaces as well, just in case we split on spaces later
|
||||
(in the case of unquoted $@, we will eventually attempt to split the
|
||||
entire word on spaces). Corresponding code exists in dequote_escapes.
|
||||
Even if we don't end up splitting on spaces, quoting spaces is not a
|
||||
problem. */
|
||||
char *
|
||||
quote_escapes (string)
|
||||
char *string;
|
||||
|
@ -2924,17 +2941,19 @@ quote_escapes (string)
|
|||
register char *s, *t;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string);
|
||||
send = string + slen;
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
t = result = (char *)xmalloc ((slen * 2) + 1);
|
||||
s = string;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if (*s == CTLESC || *s == CTLNUL)
|
||||
if (*s == CTLESC || *s == CTLNUL || (quote_spaces && *s == ' '))
|
||||
*t++ = CTLESC;
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
|
@ -2976,6 +2995,7 @@ dequote_escapes (string)
|
|||
register char *s, *t;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
if (string == 0)
|
||||
|
@ -2990,9 +3010,10 @@ dequote_escapes (string)
|
|||
if (strchr (string, CTLESC) == 0)
|
||||
return (strcpy (result, s));
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
while (*s)
|
||||
{
|
||||
if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
|
||||
if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
|
||||
{
|
||||
s++;
|
||||
if (*s == '\0')
|
||||
|
@ -3954,7 +3975,11 @@ parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
|
|||
if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
|
||||
patstr++;
|
||||
|
||||
pattern = getpattern (patstr, quoted, 1);
|
||||
/* Need to pass getpattern newly-allocated memory in case of expansion --
|
||||
the expansion code will free the passed string on an error. */
|
||||
temp1 = savestring (patstr);
|
||||
pattern = getpattern (temp1, quoted, 1);
|
||||
free (temp1);
|
||||
|
||||
temp1 = (char *)NULL; /* shut up gcc */
|
||||
switch (vtype)
|
||||
|
@ -4123,6 +4148,12 @@ unlink_fifo_list ()
|
|||
nfifo = 0;
|
||||
}
|
||||
|
||||
int
|
||||
fifos_pending ()
|
||||
{
|
||||
return nfifo;
|
||||
}
|
||||
|
||||
static char *
|
||||
make_named_pipe ()
|
||||
{
|
||||
|
@ -4172,6 +4203,12 @@ add_fifo_list (fd)
|
|||
nfds++;
|
||||
}
|
||||
|
||||
int
|
||||
fifos_pending ()
|
||||
{
|
||||
return 0; /* used for cleanup; not needed with /dev/fd */
|
||||
}
|
||||
|
||||
void
|
||||
unlink_fifo_list ()
|
||||
{
|
||||
|
@ -4456,7 +4493,15 @@ read_comsub (fd, quoted)
|
|||
/* Add the character to ISTRING, possibly after resizing it. */
|
||||
RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
|
||||
|
||||
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
|
||||
/* This is essentially quote_string inline */
|
||||
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
|
||||
istring[istring_index++] = CTLESC;
|
||||
/* Escape CTLESC and CTLNUL in the output to protect those characters
|
||||
from the rest of the word expansions (word splitting and globbing.)
|
||||
This is essentially quote_escapes inline. */
|
||||
else if (c == CTLESC)
|
||||
istring[istring_index++] = CTLESC;
|
||||
else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
|
||||
istring[istring_index++] = CTLESC;
|
||||
|
||||
istring[istring_index++] = c;
|
||||
|
@ -4578,7 +4623,8 @@ command_substitute (string, quoted)
|
|||
#if defined (JOB_CONTROL)
|
||||
set_sigchld_handler ();
|
||||
stop_making_children ();
|
||||
pipeline_pgrp = old_pipeline_pgrp;
|
||||
if (pid != 0)
|
||||
pipeline_pgrp = old_pipeline_pgrp;
|
||||
#else
|
||||
stop_making_children ();
|
||||
#endif /* JOB_CONTROL */
|
||||
|
@ -4665,6 +4711,9 @@ command_substitute (string, quoted)
|
|||
|
||||
last_command_exit_value = rc;
|
||||
rc = run_exit_trap ();
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
unlink_fifo_list ();
|
||||
#endif
|
||||
exit (rc);
|
||||
}
|
||||
else
|
||||
|
@ -4763,7 +4812,7 @@ array_length_reference (s)
|
|||
else
|
||||
t = (ind == 0) ? value_cell (var) : (char *)NULL;
|
||||
|
||||
len = STRLEN (t);
|
||||
len = MB_STRLEN (t);
|
||||
return (len);
|
||||
}
|
||||
#endif /* ARRAY_VARS */
|
||||
|
@ -4860,10 +4909,11 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
|||
char *temp, *tt;
|
||||
intmax_t arg_index;
|
||||
SHELL_VAR *var;
|
||||
int atype;
|
||||
int atype, rflags;
|
||||
|
||||
ret = 0;
|
||||
temp = 0;
|
||||
rflags = 0;
|
||||
|
||||
/* Handle multiple digit arguments, as in ${11}. */
|
||||
if (legal_number (name, &arg_index))
|
||||
|
@ -4896,6 +4946,8 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
|||
temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
? quote_string (temp)
|
||||
: quote_escapes (temp);
|
||||
else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
rflags |= W_HASQUOTEDNULL;
|
||||
}
|
||||
#endif
|
||||
else if (var = find_variable (name))
|
||||
|
@ -4923,6 +4975,7 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
|||
{
|
||||
ret = alloc_word_desc ();
|
||||
ret->word = temp;
|
||||
ret->flags |= rflags;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -5546,12 +5599,16 @@ parameter_brace_substring (varname, value, substr, quoted)
|
|||
so verify_substring_values just returns the numbers specified and we
|
||||
rely on array_subrange to understand how to deal with them). */
|
||||
tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
|
||||
#if 0
|
||||
/* array_subrange now calls array_quote_escapes as appropriate, so the
|
||||
caller no longer needs to. */
|
||||
if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
|
||||
{
|
||||
temp = tt ? quote_escapes (tt) : (char *)NULL;
|
||||
FREE (tt);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
temp = tt;
|
||||
break;
|
||||
#endif
|
||||
|
@ -5707,6 +5764,11 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
|||
vtype &= ~VT_STARSUB;
|
||||
|
||||
mflags = 0;
|
||||
if (patsub && *patsub == '/')
|
||||
{
|
||||
mflags |= MATCH_GLOBREP;
|
||||
patsub++;
|
||||
}
|
||||
|
||||
/* Malloc this because expand_string_if_necessary or one of the expansion
|
||||
functions in its call chain may free it on a substitution error. */
|
||||
|
@ -5741,13 +5803,12 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
|||
}
|
||||
|
||||
/* ksh93 doesn't allow the match specifier to be a part of the expanded
|
||||
pattern. This is an extension. */
|
||||
pattern. This is an extension. Make sure we don't anchor the pattern
|
||||
at the beginning or end of the string if we're doing global replacement,
|
||||
though. */
|
||||
p = pat;
|
||||
if (pat && pat[0] == '/')
|
||||
{
|
||||
mflags |= MATCH_GLOBREP|MATCH_ANY;
|
||||
p++;
|
||||
}
|
||||
if (mflags & MATCH_GLOBREP)
|
||||
mflags |= MATCH_ANY;
|
||||
else if (pat && pat[0] == '#')
|
||||
{
|
||||
mflags |= MATCH_BEG;
|
||||
|
@ -5798,12 +5859,16 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
|||
#if defined (ARRAY_VARS)
|
||||
case VT_ARRAYVAR:
|
||||
temp = array_patsub (array_cell (v), p, rep, mflags);
|
||||
#if 0
|
||||
/* Don't need to do this anymore; array_patsub calls array_quote_escapes
|
||||
as appropriate before adding the space separators. */
|
||||
if (temp && (mflags & MATCH_QUOTED) == 0)
|
||||
{
|
||||
tt = quote_escapes (temp);
|
||||
free (temp);
|
||||
temp = tt;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
@ -7607,6 +7672,10 @@ exp_jump_to_top_level (v)
|
|||
expand_no_split_dollar_star = 0; /* XXX */
|
||||
expanding_redir = 0;
|
||||
|
||||
if (parse_and_execute_level == 0)
|
||||
top_level_cleanup (); /* from sig.c */
|
||||
|
||||
|
||||
jump_to_top_level (v);
|
||||
}
|
||||
|
||||
|
@ -7824,7 +7893,7 @@ glob_expand_word_list (tlist, eflags)
|
|||
else if (fail_glob_expansion != 0)
|
||||
{
|
||||
report_error (_("no match: %s"), tlist->word->word);
|
||||
jump_to_top_level (DISCARD);
|
||||
exp_jump_to_top_level (DISCARD);
|
||||
}
|
||||
else if (allow_null_glob_expansion == 0)
|
||||
{
|
||||
|
|
3
subst.h
3
subst.h
|
@ -135,7 +135,7 @@ extern WORD_LIST *expand_string_unsplit __P((char *, int));
|
|||
extern WORD_LIST *expand_string_assignment __P((char *, int));
|
||||
|
||||
/* Expand a prompt string. */
|
||||
extern WORD_LIST *expand_prompt_string __P((char *, int));
|
||||
extern WORD_LIST *expand_prompt_string __P((char *, int, int));
|
||||
|
||||
/* Expand STRING just as if you were expanding a word. This also returns
|
||||
a list of words. Note that filename globbing is *NOT* done for word
|
||||
|
@ -222,6 +222,7 @@ extern WORD_LIST *expand_words_shellexp __P((WORD_LIST *));
|
|||
extern char *command_substitute __P((char *, int));
|
||||
extern char *pat_subst __P((char *, char *, char *, int));
|
||||
|
||||
extern int fifos_pending __P((void));
|
||||
extern void unlink_fifo_list __P((void));
|
||||
|
||||
extern WORD_LIST *list_string_with_quotes __P((char *));
|
||||
|
|
|
@ -430,7 +430,7 @@ Case05---3---A:B:C---
|
|||
Case06---1---A B C::---
|
||||
Case07---3---A:B:C---
|
||||
Case08---3---A:B:C---
|
||||
./new-exp.tests: line 506: /${$(($#-1))}: bad substitution
|
||||
./new-exp.tests: line 506: ${$(($#-1))}: bad substitution
|
||||
argv[1] = <a>
|
||||
argv[2] = <b>
|
||||
argv[3] = <c>
|
||||
|
|
|
@ -6,6 +6,7 @@ shopt -s cdspell
|
|||
shopt -u checkhash
|
||||
shopt -u checkwinsize
|
||||
shopt -s cmdhist
|
||||
shopt -u compat31
|
||||
shopt -u dotglob
|
||||
shopt -u execfail
|
||||
shopt -s expand_aliases
|
||||
|
@ -53,6 +54,7 @@ shopt -s sourcepath
|
|||
shopt -u cdable_vars
|
||||
shopt -u checkhash
|
||||
shopt -u checkwinsize
|
||||
shopt -u compat31
|
||||
shopt -u dotglob
|
||||
shopt -u execfail
|
||||
shopt -u extdebug
|
||||
|
@ -77,6 +79,7 @@ shopt -u xpg_echo
|
|||
cdable_vars off
|
||||
checkhash off
|
||||
checkwinsize off
|
||||
compat31 off
|
||||
dotglob off
|
||||
execfail off
|
||||
extdebug off
|
||||
|
|
16
variables.c
16
variables.c
|
@ -1821,11 +1821,17 @@ make_variable_value (var, value, flags)
|
|||
oval = value_cell (var);
|
||||
lval = evalexp (oval, &expok); /* ksh93 seems to do this */
|
||||
if (expok == 0)
|
||||
jump_to_top_level (DISCARD);
|
||||
{
|
||||
top_level_cleanup ();
|
||||
jump_to_top_level (DISCARD);
|
||||
}
|
||||
}
|
||||
rval = evalexp (value, &expok);
|
||||
if (expok == 0)
|
||||
jump_to_top_level (DISCARD);
|
||||
{
|
||||
top_level_cleanup ();
|
||||
jump_to_top_level (DISCARD);
|
||||
}
|
||||
if (flags & ASS_APPEND)
|
||||
rval += lval;
|
||||
retval = itos (rval);
|
||||
|
@ -3452,9 +3458,11 @@ push_func_var (data)
|
|||
if (shell_variables == global_variables)
|
||||
var->attributes &= ~(att_tempvar|att_propagate);
|
||||
else
|
||||
shell_variables->flags |= VC_HASTMPVAR;
|
||||
shell_variables->flags |= VC_HASTMPVAR;
|
||||
v->attributes |= var->attributes;
|
||||
}
|
||||
else
|
||||
stupidly_hack_special_variables (var->name); /* XXX */
|
||||
|
||||
dispose_variable (var);
|
||||
}
|
||||
|
@ -3541,6 +3549,8 @@ push_exported_var (data)
|
|||
var->attributes &= ~att_propagate;
|
||||
v->attributes |= var->attributes;
|
||||
}
|
||||
else
|
||||
stupidly_hack_special_variables (var->name); /* XXX */
|
||||
|
||||
dispose_variable (var);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,9 @@ const char *release_status = (char *)0;
|
|||
#endif
|
||||
const char *sccs_version = SCCSVERSION;
|
||||
|
||||
/* If == 31, shell compatible with bash-3.1, == 32 with bash-3.2, and so on */
|
||||
int shell_compatibility_level = 32;
|
||||
|
||||
/* Functions for getting, setting, and displaying the shell version. */
|
||||
|
||||
/* Forward declarations so we don't have to include externs.h */
|
||||
|
@ -79,5 +82,5 @@ show_shell_version (extended)
|
|||
{
|
||||
printf ("GNU bash, version %s (%s)\n", shell_version_string (), MACHTYPE);
|
||||
if (extended)
|
||||
printf (_("Copyright (C) 2005 Free Software Foundation, Inc.\n"));
|
||||
printf (_("Copyright (C) 2007 Free Software Foundation, Inc.\n"));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue