summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2016-11-19 02:49:15 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2016-11-19 02:50:59 -0800
commit928af46ede5d5bd3b564466042531d57b0e506bf (patch)
treeb0aebeecbb4378a14940e712dc598a3a1493cfd5
parenta99b612d1a2ce392a7ca6c59724013a965e81e04 (diff)
downloadgrep-928af46ede5d5bd3b564466042531d57b0e506bf.tar.gz
grep: -T now adjusts number widths for worst case
* NEWS, doc/grep.texi (Output Line Prefix Control): Document this (Bug#24451). * src/grep.c (offset_width): New static var. (print_offset): Use it instead of arg. All callers changed. (grep): Set it. * tests/initial-tab: Test this.
-rw-r--r--NEWS4
-rw-r--r--doc/grep.texi6
-rw-r--r--src/grep.c28
-rwxr-xr-xtests/initial-tab5
4 files changed, 32 insertions, 11 deletions
diff --git a/NEWS b/NEWS
index 0037edd7..978ec555 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,10 @@ GNU grep NEWS -*- outline -*-
longer outputs tab-backspace-':'-C, an approach that has problems if
run inside an Emacs shell window. [bug introduced in grep-2.5.2]
+ grep -T now uses worst-case widths of line numbers and byte offsets
+ instead of guessing widths that might not work with larger files.
+ [bug introduced in grep-2.5.2]
+
grep's use of getprogname no longer causes a build failure on HP-UX.
** Improvements
diff --git a/doc/grep.texi b/doc/grep.texi
index 9af13c42..3a12dce2 100644
--- a/doc/grep.texi
+++ b/doc/grep.texi
@@ -463,10 +463,8 @@ Make sure that the first character of actual line content lies on a tab stop,
so that the alignment of tabs looks normal.
This is useful with options that prefix their output to the actual content:
@option{-H}, @option{-n}, and @option{-b}.
-In order to improve the probability that lines
-from a single file will all start at the same column,
-this also causes the line number and byte offset (if present)
-to be printed in a minimum-size field width.
+This may also prepend spaces to output line numbers and byte offsets
+so that lines from a single file all start at the same column.
@item -u
@itemx --unix-byte-offsets
diff --git a/src/grep.c b/src/grep.c
index 86cf18b9..62866cbd 100644
--- a/src/grep.c
+++ b/src/grep.c
@@ -81,6 +81,9 @@ static bool only_matching;
/* If nonzero, make sure first content char in a line is on a tab stop. */
static bool align_tabs;
+/* Print width of line numbers and byte offsets. Nonzero if ALIGN_TABS. */
+static int offset_width;
+
/* See below */
struct FL_pair
{
@@ -1079,12 +1082,13 @@ print_sep (char sep)
/* Print a line number or a byte offset. */
static void
-print_offset (uintmax_t pos, int min_width, const char *color)
+print_offset (uintmax_t pos, const char *color)
{
#if !HAVE_PRINTF_C99_SIZES
/* Do not rely on printf to print pos, since uintmax_t may be longer
than long, and long long is not portable. */
+ int min_width = offset_width;
char buf[sizeof pos * CHAR_BIT];
char *p = buf + sizeof buf;
@@ -1096,14 +1100,13 @@ print_offset (uintmax_t pos, int min_width, const char *color)
while ((pos /= 10) != 0);
/* Do this to maximize the probability of alignment across lines. */
- if (align_tabs)
- while (--min_width >= 0)
- *--p = ' ';
+ while (--min_width >= 0)
+ *--p = ' ';
#endif /* !HAVE_PRINTF_C99_SIZES */
pr_sgr_start_if (color);
#if HAVE_PRINTF_C99_SIZES
- printf_errno ("%*ju", align_tabs ? min_width : 0, pos);
+ printf_errno ("%*ju", offset_width, pos);
#else
fwrite_errno (p, 1, buf + sizeof buf - p);
#endif
@@ -1151,7 +1154,7 @@ print_line_head (char *beg, size_t len, char const *lim, char sep)
totalnl = add_count (totalnl, 1);
lastnl = lim;
}
- print_offset (totalnl, 4, line_num_color);
+ print_offset (totalnl, line_num_color);
print_sep (sep);
}
@@ -1159,7 +1162,7 @@ print_line_head (char *beg, size_t len, char const *lim, char sep)
{
uintmax_t pos = add_count (totalcc, beg - bufbeg);
pos = dossified_pos (pos);
- print_offset (pos, 6, byte_num_color);
+ print_offset (pos, byte_num_color);
print_sep (sep);
}
@@ -1511,6 +1514,17 @@ grep (int fd, struct stat const *st, bool *ineof)
return 0;
}
+ offset_width = 0;
+ if (align_tabs)
+ {
+ /* Width is log of maximum number. Line numbers are origin-1. */
+ uintmax_t num = usable_st_size (st) ? st->st_size : UINTMAX_MAX;
+ num += out_line && num < UINTMAX_MAX;
+ do
+ offset_width++;
+ while ((num /= 10) != 0);
+ }
+
for (bool firsttime = true; ; firsttime = false)
{
if (nlines_first_null < 0 && eol && binary_files != TEXT_BINARY_FILES
diff --git a/tests/initial-tab b/tests/initial-tab
index af5efb37..8b3cb8c4 100755
--- a/tests/initial-tab
+++ b/tests/initial-tab
@@ -29,4 +29,9 @@ printf 'in:\tx\nin:\n' > exp || framework_failure_
grep -T '^' in /dev/null > out || fail=1
compare exp out || fail=1
+printf '%s\n' a b c d e f g h i j > in1 || framework_failure_
+printf 'in1: 1:\ta\n' > exp1 || framework_failure_
+grep -Tn 'a' in1 /dev/null > out1 || fail=1
+compare exp1 out1 || fail=1
+
Exit $fail