summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2017-02-22 11:09:11 -0500
committerChet Ramey <chet.ramey@case.edu>2017-02-22 11:09:11 -0500
commitac495185aab17ef6030a02ddc0be33380a27a94d (patch)
tree3016c147c550e606b2a44f086784ffe0afba1128
parent7e92fb358bb54f5acd5e71ef2d8f5e841c5d4320 (diff)
downloadbash-ac495185aab17ef6030a02ddc0be33380a27a94d.tar.gz
commit bash-20170210 snapshot
-rw-r--r--CWRU/CWRU.chlog50
-rw-r--r--MANIFEST1
-rw-r--r--doc/bash.110
-rw-r--r--doc/bashref.texi2
-rw-r--r--doc/version.texi4
-rw-r--r--eval.c41
-rw-r--r--execute_cmd.c2
-rw-r--r--externs.h1
-rw-r--r--jobs.c11
-rw-r--r--lib/readline/display.c100
-rw-r--r--lib/readline/mbutil.c11
-rw-r--r--parse.y2
-rw-r--r--shell.c11
-rwxr-xr-xtests/RUN-ONE-TEST2
-rw-r--r--tests/comsub.right7
-rw-r--r--tests/comsub.tests1
-rw-r--r--tests/comsub4.sub27
17 files changed, 211 insertions, 72 deletions
diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog
index 0c79193..5ab464e 100644
--- a/CWRU/CWRU.chlog
+++ b/CWRU/CWRU.chlog
@@ -13115,3 +13115,53 @@ lib/readline/input.c
the next character as an unsigned char, so we handle multibyte
character sequences correctly. Report and fix from Grisha Levit
<grishalevit@gmail.com>
+
+ 2/6
+ ---
+shell.c
+ - --pretty-print: new invocation option, currently undocumented, dumps
+ a pretty-printed version of a shell script given as an argument to
+ stdout
+ - main: call pretty_print_loop() if we're in pretty-printing mode in
+ a non-interactive shell
+
+eval.c
+ - pretty_print_loop: new function, similar to reader_loop, reads
+ commands and prints them by displaying the result from
+ make_command_string()
+
+externs.h
+ - pretty_print_loop: new extern declaration
+
+ 2/9
+ ---
+doc/{bash.1,bashref.texi}
+ - here strings: correct documentation to note they do not undergo
+ brace expansion. Report from Conor McCarthy <mr.spuratic@gmail.com>
+
+ 2/9
+ ---
+lib/readline/display.c
+ - expand_prompt: instead of recomputing the line break offsets for
+ prompts that span multiple screen lines on every call to rl_redisplay,
+ do it here. Manage a local array local_prompt_newlines; set an offset
+ every time `physchars' hits a multiple of the screen width. Inspired
+ by https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=843819
+ - rl_redisplay: don't calculate multi-line prompt line break indices
+ here; use the values calculated by expand_prompt
+ - rl_{save,restore}_prompt: save and restore local_prompt_newlines
+
+ 2/11
+ ----
+lib/readline/mbutil.c
+ - _rl_find_prev_mbchar_internal: since we're traversing the string
+ from the beginning, shortcut non-multibyte characters in a UTF-8
+ locale
+
+parse.y
+ - parse_comsub: if we are parsing a here document with a quoted
+ delimiter (LEX_QUOTEDDOC), we should not remove <backslash><newline>
+ pairs from the body of the here document. Need to add LEX_QUOTEDDOC
+ to the values in tflags when calling shell_getc. Fixes bug reported
+ by Michael Homer <michael.homer@ecs.vuw.ac.nz>, patch was originally
+ contributed by Geir Hauge <geir.hauge@gmail.com>
diff --git a/MANIFEST b/MANIFEST
index 7faeeb1..455a593 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -899,6 +899,7 @@ tests/comsub.right f
tests/comsub1.sub f
tests/comsub2.sub f
tests/comsub3.sub f
+tests/comsub4.sub f
tests/comsub-eof.tests f
tests/comsub-eof0.sub f
tests/comsub-eof1.sub f
diff --git a/doc/bash.1 b/doc/bash.1
index b55462c..e34e94f 100644
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -5,12 +5,12 @@
.\" Case Western Reserve University
.\" chet.ramey@case.edu
.\"
-.\" Last Change: Fri Feb 3 16:01:50 EST 2017
+.\" Last Change: Thu Feb 9 15:46:36 EST 2017
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
-.TH BASH 1 "2017 February 3" "GNU Bash 4.4"
+.TH BASH 1 "2017 February 9" "GNU Bash 4.4"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
@@ -50,8 +50,8 @@ bash \- GNU Bourne-Again SHell
[options]
[command_string | file]
.SH COPYRIGHT
-.if n Bash is Copyright (C) 1989-2016 by the Free Software Foundation, Inc.
-.if t Bash is Copyright \(co 1989-2016 by the Free Software Foundation, Inc.
+.if n Bash is Copyright (C) 1989-2017 by the Free Software Foundation, Inc.
+.if t Bash is Copyright \(co 1989-2017 by the Free Software Foundation, Inc.
.SH DESCRIPTION
.B Bash
is an \fBsh\fR-compatible command language interpreter that
@@ -4017,7 +4017,7 @@ A variant of here documents, the format is:
.RE
.PP
The \fIword\fP undergoes
-brace expansion, tilde expansion, parameter and variable expansion,
+tilde expansion, parameter and variable expansion,
command substitution, arithmetic expansion, and quote removal.
Pathname expansion and word splitting are not performed.
The result is supplied as a single string, with a newline appended,
diff --git a/doc/bashref.texi b/doc/bashref.texi
index 287abf0..fb15067 100644
--- a/doc/bashref.texi
+++ b/doc/bashref.texi
@@ -2773,7 +2773,7 @@ A variant of here documents, the format is:
@end example
The @var{word} undergoes
-brace expansion, tilde expansion, parameter and variable expansion,
+tilde expansion, parameter and variable expansion,
command substitution, arithmetic expansion, and quote removal.
Pathname expansion and word splitting are not performed.
The result is supplied as a single string,
diff --git a/doc/version.texi b/doc/version.texi
index 3e05e24..96373ff 100644
--- a/doc/version.texi
+++ b/doc/version.texi
@@ -2,10 +2,10 @@
Copyright (C) 1988-2017 Free Software Foundation, Inc.
@end ignore
-@set LASTCHANGE Wed Feb 1 09:09:18 EST 2017
+@set LASTCHANGE Thu Feb 9 15:46:16 EST 2017
@set EDITION 4.4
@set VERSION 4.4
-@set UPDATED 1 February 2017
+@set UPDATED 9 February 2017
@set UPDATED-MONTH February 2017
diff --git a/eval.c b/eval.c
index c2ebf55..28a3bdc 100644
--- a/eval.c
+++ b/eval.c
@@ -193,6 +193,47 @@ reader_loop ()
return (last_command_exit_value);
}
+/* Pretty print shell scripts */
+int
+pretty_print_loop ()
+{
+ COMMAND *current_command;
+ char *command_to_print;
+ int code;
+ int global_posix_mode, last_was_newline;
+
+ global_posix_mode = posixly_correct;
+ last_was_newline = 0;
+ while (EOF_Reached == 0)
+ {
+ code = setjmp_nosigs (top_level);
+ if (code)
+ return (EXECUTION_FAILURE);
+ if (read_command() == 0)
+ {
+ current_command = global_command;
+ global_command = 0;
+ posixly_correct = 1; /* print posix-conformant */
+ if (current_command && (command_to_print = make_command_string (current_command)))
+ {
+ printf ("%s\n", command_to_print); /* for now */
+ last_was_newline = 0;
+ }
+ else if (last_was_newline == 0)
+ {
+ printf ("\n");
+ last_was_newline = 1;
+ }
+ posixly_correct = global_posix_mode;
+ dispose_command (current_command);
+ }
+ else
+ return (EXECUTION_FAILURE);
+ }
+
+ return (EXECUTION_SUCCESS);
+}
+
static sighandler
alrm_catcher(i)
int i;
diff --git a/execute_cmd.c b/execute_cmd.c
index feccf7c..3074fa2 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -271,6 +271,8 @@ static int function_line_number;
report the correct line number. Kind of a hack. */
static int showing_function_line;
+static int connection_count;
+
/* $LINENO ($BASH_LINENO) for use by an ERR trap. Global so parse_and_execute
can save and restore it. */
int line_number_for_err_trap;
diff --git a/externs.h b/externs.h
index 925e946..9faf305 100644
--- a/externs.h
+++ b/externs.h
@@ -94,6 +94,7 @@ extern void get_current_user_info __P((void));
/* Functions from eval.c. */
extern int reader_loop __P((void));
+extern int pretty_print_loop __P((void));
extern int parse_command __P((void));
extern int read_command __P((void));
diff --git a/jobs.c b/jobs.c
index b9abebf..dfc4b25 100644
--- a/jobs.c
+++ b/jobs.c
@@ -848,8 +848,15 @@ bgp_delete (pid)
/* Search chain using hash to find bucket in pidstat_table */
for (psi = *(pshash_getbucket (pid)); psi != NO_PIDSTAT; psi = bgpids.storage[psi].bucket_next)
- if (bgpids.storage[psi].pid == pid)
- break;
+ {
+ if (bgpids.storage[psi].pid == pid)
+ break;
+ if (psi == bgpids.storage[psi].bucket_next) /* catch reported bug */
+ {
+ internal_warning ("bgp_delete: BUG: psi (%d) == storage[psi].bucket_next", psi);
+ return 0;
+ }
+ }
if (psi == NO_PIDSTAT)
return 0; /* not found */
diff --git a/lib/readline/display.c b/lib/readline/display.c
index 0e0d44c..50a8688 100644
--- a/lib/readline/display.c
+++ b/lib/readline/display.c
@@ -251,6 +251,8 @@ static int modmark;
static char *saved_local_prompt;
static char *saved_local_prefix;
+static int *saved_local_prompt_newlines;
+
static int saved_last_invisible;
static int saved_visible_length;
static int saved_prefix_length;
@@ -303,6 +305,8 @@ prompt_modestr (lenp)
PMT_MULTILINE caller indicates that this is part of a multiline prompt
*/
+static int *local_prompt_newlines;
+
static char *
expand_prompt (pmt, flags, lp, lip, niflp, vlp)
char *pmt;
@@ -311,7 +315,7 @@ expand_prompt (pmt, flags, lp, lip, niflp, vlp)
{
char *r, *ret, *p, *igstart, *nprompt, *ms;
int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
- int mlen;
+ int mlen, newlines, newlines_guess, bound;
/* We only expand the mode string for the last line of a multiline prompt
(a prompt with embedded newlines). */
@@ -345,6 +349,12 @@ expand_prompt (pmt, flags, lp, lip, niflp, vlp)
l = strlen (nprompt); /* XXX */
r = ret = (char *)xmalloc (l + 1);
+ newlines_guess = (l / _rl_screenwidth) + 1;
+ local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * (newlines_guess + 1));
+ local_prompt_newlines[newlines = 0] = 0;
+ for (rl = 1; rl <= newlines_guess; rl++)
+ local_prompt_newlines[rl] = -1;
+
rl = physchars = 0; /* mode string now part of nprompt */
invfl = 0; /* invisible chars in first line of prompt */
invflset = 0; /* we only want to set invfl once */
@@ -404,11 +414,25 @@ expand_prompt (pmt, flags, lp, lip, niflp, vlp)
ninvis++; /* invisible chars byte counter */
}
- if (invflset == 0 && rl >= _rl_screenwidth)
+ if (invflset == 0 && physchars >= _rl_screenwidth)
{
invfl = ninvis;
invflset = 1;
}
+#if 0
+ if (physchars >= ((newlines + 1) * _rl_screenwidth) && local_prompt_newlines[newlines+1] == -1)
+ local_prompt_newlines[++newlines] = r - ret;
+#else
+ if (physchars >= (bound = (newlines + 1) * _rl_screenwidth) && local_prompt_newlines[newlines+1] == -1)
+ {
+ int new;
+ if (physchars > bound) /* should rarely happen */
+ new = _rl_find_prev_mbchar (r, r - ret, MB_FIND_ANY);
+ else
+ new = r - ret;
+ local_prompt_newlines[++newlines] = new;
+ }
+#endif
}
}
@@ -759,18 +783,9 @@ rl_redisplay ()
/* what if lpos is already >= _rl_screenwidth before we start drawing the
contents of the command line? */
- while (lpos >= _rl_screenwidth)
+ if (lpos >= _rl_screenwidth)
{
- int z, p;
- int nocorrect, wadjust;
-
- nocorrect = 0;
- /* Adjust depending on the invisible characters in the line. We use a
- heuristic based on experience: invisible characters nearly always
- appear in the first and last lines of the prompt */
- wadjust = (newlines == 0)
- ? prompt_invis_chars_first_line
- : ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line);
+ temp = 0;
/* fix from Darin Johnson <darin@acuson.com> for prompt string with
invisible characters that is longer than the screen width. The
@@ -779,55 +794,18 @@ rl_redisplay ()
probably too much work for the benefit gained. How many people have
prompts that exceed two physical lines?
Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
-#if defined (HANDLE_MULTIBYTE)
- if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
+ /* first copy the linebreaks array we computed in expand_prompt */
+ while (local_prompt_newlines[newlines+1] != -1)
{
- nocorrect = 1;
- n0 = num;
- temp = local_prompt_len;
- while (num < temp)
- {
- /* This has to take invisible characters in the prompt into
- account. */
- z = _rl_col_width (local_prompt, n0, num, 1) - wadjust;
- if (z > _rl_screenwidth)
- {
- num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
- break;
- }
- else if (z == _rl_screenwidth)
- {
- /* If we are in the middle or at the end of a multibyte
- character, we want to move to the start, then find out
- where it ends so we know where to insert the newline.
- If this isn't a multibyte character, its the same as num++ */
- p = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
- num = _rl_find_next_mbchar (local_prompt, p, 1, MB_FIND_ANY);
- break;
- }
- num++;
- }
- temp = num;
- }
- else
-#endif /* !HANDLE_MULTIBYTE */
- temp = ((newlines + 1) * _rl_screenwidth);
-
- /* 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. */
- if (nocorrect == 0)
- temp += wadjust;
+ temp = local_prompt_newlines[newlines+1];
+ inv_lbreaks[++newlines] = temp;
+ }
- inv_lbreaks[++newlines] = temp;
-#if defined (HANDLE_MULTIBYTE)
- /* lpos is a physical cursor position, so it needs to take the invisible
- characters into account. */
+ /* Now set lpos from the last newline */
if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
- lpos -= _rl_col_width (local_prompt, n0, num, 1) - wadjust;
+ lpos = _rl_col_width (local_prompt, temp, local_prompt_len, 1) - (wrap_offset - prompt_invis_chars_first_line);
else
-#endif
- lpos -= _rl_screenwidth; /* all physical cursor positions */
+ lpos -= (_rl_screenwidth * newlines);
}
prompt_last_screen_line = newlines;
@@ -2561,9 +2539,12 @@ rl_save_prompt ()
saved_visible_length = prompt_visible_length;
saved_invis_chars_first_line = prompt_invis_chars_first_line;
saved_physical_chars = prompt_physical_chars;
+ saved_local_prompt_newlines = local_prompt_newlines;
local_prompt = local_prompt_prefix = (char *)0;
local_prompt_len = 0;
+ local_prompt_newlines = (int *)0;
+
prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
prompt_invis_chars_first_line = prompt_physical_chars = 0;
}
@@ -2573,10 +2554,13 @@ rl_restore_prompt ()
{
FREE (local_prompt);
FREE (local_prompt_prefix);
+ FREE (local_prompt_newlines);
local_prompt = saved_local_prompt;
local_prompt_prefix = saved_local_prefix;
local_prompt_len = saved_local_length;
+ local_prompt_newlines = saved_local_prompt_newlines;
+
prompt_prefix_length = saved_prefix_length;
prompt_last_invisible = saved_last_invisible;
prompt_visible_length = saved_visible_length;
diff --git a/lib/readline/mbutil.c b/lib/readline/mbutil.c
index df1c484..6485278 100644
--- a/lib/readline/mbutil.c
+++ b/lib/readline/mbutil.c
@@ -1,6 +1,6 @@
/* mbutil.c -- readline multibyte character utility functions */
-/* Copyright (C) 2001-2015 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2017 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.
@@ -173,7 +173,14 @@ _rl_find_prev_mbchar_internal (string, seed, find_non_zero)
prev = non_zero_prev = point = 0;
while (point < seed)
{
- tmp = mbrtowc (&wc, string + point, length - point, &ps);
+ if (_rl_utf8locale && UTF8_SINGLEBYTE(string[point]))
+ {
+ tmp = 1;
+ wc = (wchar_t) string[point];
+ memset(&ps, 0, sizeof(mbstate_t));
+ }
+ else
+ tmp = mbrtowc (&wc, string + point, length - point, &ps);
if (MB_INVALIDCH ((size_t)tmp))
{
/* in this case, bytes are invalid or too short to compose
diff --git a/parse.y b/parse.y
index 171f2e2..84b81c8 100644
--- a/parse.y
+++ b/parse.y
@@ -3757,7 +3757,7 @@ parse_comsub (qc, open, close, lenp, flags)
while (count)
{
comsub_readchar:
- ch = shell_getc (qc != '\'' && (tflags & (LEX_INCOMMENT|LEX_PASSNEXT)) == 0);
+ ch = shell_getc (qc != '\'' && (tflags & (LEX_INCOMMENT|LEX_PASSNEXT|LEX_QUOTEDDOC)) == 0);
if (ch == EOF)
{
diff --git a/shell.c b/shell.c
index f577ae2..17962a9 100644
--- a/shell.c
+++ b/shell.c
@@ -223,6 +223,8 @@ int dump_po_strings; /* Dump strings in $"..." in po format */
int wordexp_only = 0; /* Do word expansion only */
int protected_mode = 0; /* No command substitution with --wordexp */
+int pretty_print_mode = 0; /* pretty-print a shell script */
+
#if defined (STRICT_POSIX)
int posixly_correct = 1; /* Non-zero means posix.2 superset. */
#else
@@ -251,6 +253,7 @@ static const struct {
{ "noprofile", Int, &no_profile, (char **)0x0 },
{ "norc", Int, &no_rc, (char **)0x0 },
{ "posix", Int, &posixly_correct, (char **)0x0 },
+ { "pretty-print", Int, &pretty_print_mode, (char **)0x0 },
#if defined (WORDEXP_OPTION)
{ "protected", Int, &protected_mode, (char **)0x0 },
#endif
@@ -779,6 +782,14 @@ main (argc, argv, env)
shell_initialized = 1;
+ if (pretty_print_mode && interactive_shell)
+ {
+ internal_warning (_("pretty-printing mode ignored in interactive shells"));
+ pretty_print_mode = 0;
+ }
+ if (pretty_print_mode)
+ exit_shell (pretty_print_loop ());
+
/* Read commands until exit condition. */
reader_loop ();
exit_shell (last_command_exit_value);
diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST
index 58c375b..554f3d6 100755
--- a/tests/RUN-ONE-TEST
+++ b/tests/RUN-ONE-TEST
@@ -1,4 +1,4 @@
-BUILD_DIR=/usr/local/build/chet/bash/bash-current
+BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
diff --git a/tests/comsub.right b/tests/comsub.right
index 09518aa..71bb205 100644
--- a/tests/comsub.right
+++ b/tests/comsub.right
@@ -28,6 +28,7 @@ ok 4
ok 5
ok 6
xyz
+ok 7
\/tmp\/foo\/bar
/tmp/foo/bar
/tmp/foo/bar
@@ -48,3 +49,9 @@ b
c
1
2
+d \
+g
+d \
+g
+d \
+g
diff --git a/tests/comsub.tests b/tests/comsub.tests
index 4defc31..e8fab71 100644
--- a/tests/comsub.tests
+++ b/tests/comsub.tests
@@ -47,3 +47,4 @@ echo ${foo:-$(echo a{b,c})} >/dev/null
${THIS_SH} ./comsub1.sub
${THIS_SH} ./comsub2.sub
${THIS_SH} ./comsub3.sub
+${THIS_SH} ./comsub4.sub
diff --git a/tests/comsub4.sub b/tests/comsub4.sub
new file mode 100644
index 0000000..461a9ad
--- /dev/null
+++ b/tests/comsub4.sub
@@ -0,0 +1,27 @@
+x=$(cat <<'EOT'
+d \
+g
+EOT
+)
+
+echo "$x"
+unset x
+
+x=$( cat <<\EOT\
+4
+d \
+g
+EOT4
+)
+
+echo "$x"
+unset x
+
+x=$( cat <<\EOT
+d \
+g
+EOT
+)
+
+echo "$x"
+