summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1996-12-05 04:33:33 +0000
committerJim Meyering <jim@meyering.net>1996-12-05 04:33:33 +0000
commited0923a11c1cde29b423c83b3f22be3d2b73f464 (patch)
tree6c14553d8fb852e3e8ae57f2327c21052be8cc62 /src
parent42096600e32f6e06a015233988825493a3840cf7 (diff)
downloadcoreutils-ed0923a11c1cde29b423c83b3f22be3d2b73f464.tar.xz
Apply big patch (patch-20) from Roland Huebner.
Diffstat (limited to 'src')
-rw-r--r--src/pr.c964
1 files changed, 763 insertions, 201 deletions
diff --git a/src/pr.c b/src/pr.c
index 2883ec0e0..7e20e3c38 100644
--- a/src/pr.c
+++ b/src/pr.c
@@ -32,10 +32,12 @@
Options:
- +PAGE Begin output at page PAGE of the output.
+ +FIRST_PAGE[:LAST_PAGE]
+ begin [stop] printing with page FIRST_[LAST_]PAGE
-COLUMN Produce output that is COLUMN columns wide and print
columns down.
+ Balance columns on the last page is automatically set.
-a Print columns across rather than down. The input
one
@@ -47,6 +49,21 @@
four
-b Balance columns on the last page.
+ -b is no longer an independent option. It's always used
+ together with -COLUMN (unless -a is used) to get a
+ consistent formulation with "FF set by hand" in input
+ files. Each formfeed found terminates the number of lines
+ to be read with the actual page. The situation for
+ printing columns down is equivalent to that on the last
+ page. So we need a balancing.
+
+ We do not yet eliminate source text dealing with -COLUMN
+ only. Tune this if it proved to be a satisfactory
+ procedure.
+
+ Keeping -b as an underground option guarantees some
+ downward compatibility. Utilities using pr with -b
+ (a most frequently used form) still work as usual.
-c Print unprintable characters as control prefixes.
Control-g is printed as ^G.
@@ -59,23 +76,54 @@
-F
-f Use formfeeds instead of newlines to separate pages.
+ A three line HEADER is used, no TRAILER (without -f
+ both HEADER and TRAILER are made of five lines).
- -h header Replace the filename in the header with the string HEADER.
+ -h HEADER Replace the filename in the header with the string HEADER.
+ Checking and left-hand-side truncation of the length of the
+ standard and custom header string. A centered header is used.
+ The format of date and time has been shortened
+ to yy-mm-dd HH:MM to give place to a maximal filename
+ information.
+ -h "" now prints a blank line header. -h"" shows an error.
-i[c[k]] Replace spaces with tabs on output. Optional argument
C is the output tab character. (Default is `\t'.) Optional
argument K is the output tab character's width. (Default
is 8.)
+ -j Merge full lines, turns off -w line truncation, no column
+ alignment, -s[STRING] sets separators, works with all
+ column options (-COLUMN | -a -COLUMN | -m).
+
-l lines Set the page length to LINES. Default is 66.
- -m Print files in parallel.
+ -m Print files in parallel; pad_across_to align columns;
+ truncate lines and print separator strings;
+ Do it also with empty columns to get a continuous line
+ numbering and column marking by separators throughout
+ the whole merged file.
+
+ Empty pages in some input files produce empty columns
+ [marked by separators] in the common pages. Completely
+ empty common pages show no column separators at all.
+
+ The layout of a merged page is ruled by the largest form
+ feed distance of the single pages at that page. Shorter
+ columns will be filled up with empty lines.
+
+ Together with -j option join lines of full length and
+ in addition set separators when -s option is used.
-n[c[k]] Precede each column with a line number.
(With parallel files, precede each line with a line
number.) Optional argument C is the character to print
after each number. (Default `\t'.) Optional argument
- K is the number of digits per line number. (Default 5.)
+ k is the number of digits per line number. (Default 5.)
+ Default counting starts with 1st line of input file.
+
+ -N number Start counting with number at 1st line of first page
+ printed.
-o offset Offset each line with a margin OFFSET spaces wide.
Total page width is the size of this offset plus the
@@ -83,15 +131,41 @@
-r Ignore files that can't be opened.
- -s[c] Separate each line with a character. Optional argument C is
- the character to be used. Default is `\t'.
+ -s[STRING] Separate columns by any string STRING.
+ Don't use -s "STRING".
+ without -s: default separator 'space' s used,
+ same as -s" ",
+ with -s only: no separator is used, same as -s"".
+ Quotes should be used with blanks and some shell active
+ characters.
+
+ -t Do not print headers or footers but retain form feeds
+ set in input files (some page layout is not changed).
- -t Do not print headers or footers.
+ -T Do not print headers or footers, eliminate form feeds
+ in input files.
-v Print unprintable characters as escape sequences.
Control-G becomes \007.
- -w width Set the page width to WIDTH characters. */
+ -w width Set the page width to WIDTH characters.
+ (In pr versions newer than 1.14 -s option does no longer
+ affect -w option.)
+
+ With/without -w width the header line is truncated.
+ Default is 72 characters.
+ With -w width text lines will be truncated, unless -j is
+ used. Together with one of the column options
+ (-COLUMN| -a -COLUMN| -m) column alignment is used.
+ Without -w PAGE_WIDTH
+ - but with one of the column options default truncation of
+ 72 characters is used (to keep downward compatibility
+ and to simplify most frequently met column tasks).
+ Column alignment and column separators are used.
+ - and without any of the column options no line truncation
+ is used (to keep downward compatibility and to meet most
+ frequent tasks). That's equivalent to -w 72 -j .
+*/
#include <config.h>
@@ -102,10 +176,23 @@
#include <time.h>
#include "system.h"
#include "error.h"
+#include "xstrtol.h"
+
+#if HAVE_LIMITS_H
+#include <limits.h>
+#endif
char *xmalloc ();
char *xrealloc ();
+#ifndef UINT_MAX
+#define UINT_MAX ((unsigned int) ~(unsigned int) 0)
+#endif
+
+#ifndef INT_MAX
+#define INT_MAX ((int) (UINT_MAX >> 1))
+#endif
+
#ifndef TRUE
#define TRUE 1
#define FALSE 0
@@ -156,46 +243,63 @@ char *xrealloc ();
numbered True means precede this column with a line number. */
struct COLUMN
-{
- FILE *fp; /* Input stream for this column. */
- char *name; /* File name. */
- enum
{
- OPEN,
- ON_HOLD, /* Hit a form feed. */
- CLOSED
- } status; /* Status of the file pointer. */
- int (*print_func) (); /* Func to print lines in this col. */
- void (*char_func) (); /* Func to print/store chars in this col. */
- int current_line; /* Index of current place in line_vector. */
- int lines_stored; /* Number of lines stored in buff. */
- int lines_to_print; /* No. lines stored or space left on page. */
- int start_position; /* Horizontal position of first char. */
- int numbered;
-};
+ FILE *fp; /* Input stream for this column. */
+ char *name; /* File name. */
+ enum
+ {
+ OPEN,
+ FF_FOUND, /* used with -b option, set with \f, changed
+ to ON_HOLD after print_header */
+ ON_HOLD, /* Hit a form feed. */
+ CLOSED
+ }
+ status; /* Status of the file pointer. */
+ int (*print_func) (); /* Func to print lines in this col. */
+ void (*char_func) (); /* Func to print/store chars in this col. */
+ int current_line; /* Index of current place in line_vector. */
+ int lines_stored; /* Number of lines stored in buff. */
+ int lines_to_print; /* No. lines stored or space left on page. */
+ int start_position; /* Horizontal position of first char. */
+ int numbered;
+ int full_page_printed; /* True means printed without a FF found. */
+
+ /* p->full_page_printed controls a special case of "FF set by hand":
+ True means a full page has been printed without FF found. To avoid an
+ additional empty page we have to ignore a FF immediately following in
+ the next line. */
+ };
typedef struct COLUMN COLUMN;
#define NULLCOL (COLUMN *)0
static int char_to_clump __P ((int c));
-static int read_line __P ((COLUMN *p));
+static int read_line __P ((COLUMN * p));
static int print_page __P ((void));
-static int print_stored __P ((COLUMN *p));
-static int open_file __P ((char *name, COLUMN *p));
+static int print_stored __P ((COLUMN * p));
+static int open_file __P ((char *name, COLUMN * p));
static int skip_to_page __P ((int page));
+static void print_header __P ((void));
+static void pad_across_to __P ((int position));
+static void number __P ((COLUMN * p));
static void getoptarg __P ((char *arg, char switch_char, char *character, int *number));
static void usage __P ((int status));
static void print_files __P ((int number_of_files, char **av));
+static void init_parameters __P ((int number_of_files));
static void init_header __P ((char *filename, int desc));
static void init_store_cols __P ((void));
static void store_columns __P ((void));
static void balance __P ((int total_stored));
static void store_char __P ((int c));
static void pad_down __P ((int lines));
-static void read_rest_of_line __P ((COLUMN *p));
+static void read_rest_of_line __P ((COLUMN * p));
+static void skip_read __P ((COLUMN * p, int column_number));
static void print_char __P ((int c));
static void cleanup __P ((void));
+static void first_last_page __P ((char *pages));
+static void print_sep_string __P ((void));
+static void separator_string (char *optarg_S);
/* The name under which this program was invoked. */
char *program_name;
@@ -205,7 +309,7 @@ static COLUMN *column_vector;
/* When printing a single file in multiple downward columns,
we store the leftmost columns contiguously in buff.
- To print a line from buff, get the index of the first char
+ To print a line from buff, get the index of the first character
from line_vector[i], and print up to line_vector[i + 1]. */
static char *buff;
@@ -233,13 +337,33 @@ static int *end_vector;
/* (-m) True means we're printing multiple files in parallel. */
static int parallel_files = FALSE;
+/* (-m) True means a line starts with some empty columns (some files
+ already CLOSED or ON_HOLD) which we have to align. */
+static int align_empty_cols;
+
+/* (-m) True means we have not yet found any printable column in a line.
+ align_empty_cols = TRUE has to be maintained. */
+static int empty_line;
+
+/* (-m) False means printable column output precedes a form feed found.
+ Column align is done only once. No additional action with that form
+ feed.
+ True means we found only a form feed in a column. Maybe we have to do
+ some column align with that form feed. */
+static int FF_only;
+
/* (-[0-9]+) True means we're given an option explicitly specifying
number of columns. Used to detect when this option is used with -m. */
static int explicit_columns = FALSE;
-/* (-t) True means we're printing headers and footers. */
+/* (-t|-T) False means we aren't printing headers and footers. */
static int extremities = TRUE;
+/* (-t) True means we retain all FF set by hand in input files.
+ False is set with -T option. */
+static int keep_FF = FALSE;
+static int print_a_FF = FALSE;
+
/* True means we need to print a header as soon as we know we've got input
to print after it. */
static int print_a_header;
@@ -261,6 +385,9 @@ static int print_across_flag = FALSE;
static int storing_columns = TRUE;
/* (-b) True means balance columns on the last page as Sys V does. */
+/* That's no longer an independent option. With storing_columns = TRUE
+ balance_columns = TRUE is used too (s. function init_parameters).
+ We get a consistent formulation with "FF set by hand" in input files. */
static int balance_columns = FALSE;
/* (-l) Number of lines on a page, including header and footer lines. */
@@ -276,7 +403,15 @@ static int lines_per_footer = 5;
the margin. */
static int chars_per_line = 72;
-/* Number of characters in a column. Based on the gutter and page widths. */
+/* (-w) True means we truncate lines longer than chars_per_column. */
+static int truncate_lines = FALSE;
+
+/* (-j) True means we join lines without any line truncation. -j
+ dominates -w option. */
+static int join_lines = FALSE;
+
+/* Number of characters in a column. Based on col_sep_length and
+ page width. */
static int chars_per_column;
/* (-e) True means convert tabs to spaces on input. */
@@ -303,11 +438,6 @@ static int chars_per_output_tab = 8;
if necessary to get to output_position + spaces_not_printed. */
static int spaces_not_printed;
-/* Number of spaces between columns (though tabs can be used when possible to
- use up the equivalent amount of space). Not sure if this is worth making
- a flag for. BSD uses 0, Sys V uses 1. Sys V looks better. */
-static int chars_per_gutter = 1;
-
/* (-o) Number of spaces in the left margin (tabs used when possible). */
static int chars_per_margin = 0;
@@ -338,8 +468,9 @@ static int failed_opens = 0;
/* (-NNN) Number of columns of text to print. */
static int columns = 1;
-/* (+NNN) Page number on which to begin printing. */
+/* (+NNN:MMM) Page numbers on which to begin and stop printing. */
static int first_page_number = 1;
+static int last_page_number = 0;
/* Number of files open (not closed, not on hold). */
static int files_ready_to_read = 0;
@@ -350,16 +481,16 @@ static int page_number;
/* Current line number. Displayed when -n flag is specified.
When printing files in parallel (-m flag), line numbering is as follows:
- 1 foo goo moo
- 2 hoo too zoo
+ 1 foo goo moo
+ 2 hoo too zoo
When printing files across (-a flag), ...
- 1 foo 2 moo 3 goo
- 4 hoo 3 too 6 zoo
+ 1 foo 2 moo 3 goo
+ 4 hoo 3 too 6 zoo
Otherwise, line numbering is as follows:
- 1 foo 3 goo 5 too
- 2 moo 4 hoo 6 zoo */
+ 1 foo 3 goo 5 too
+ 2 moo 4 hoo 6 zoo */
static int line_number;
/* (-n) True means lines should be preceded by numbers. */
@@ -368,6 +499,19 @@ static int numbered_lines = FALSE;
/* (-n) Character which follows each line number. */
static char number_separator = '\t';
+/* (-n) line counting starts with 1st line of input file (not with 1st
+ line of 1st page printed). */
+static int line_count = 1;
+
+/* (-n) True means counting of skipped lines starts with 1st line of
+ input file. False means -N option is used in addition, counting of
+ skipped lines not required. */
+static int skip_count = TRUE;
+
+/* (-N) Counting starts with start_line_number = NUMBER at 1st line of
+ first page printed, usually not 1st page of input file. */
+static int start_line_num = 1;
+
/* (-n) Width in characters of a line number. */
static int chars_per_number = 5;
@@ -397,11 +541,15 @@ static int total_files = 0;
/* (-r) True means don't complain if we can't open a file. */
static int ignore_failed_opens = FALSE;
-/* (-s) True means we separate columns with a specified character. */
-static int use_column_separator = FALSE;
+/* (-s) True means we separate columns with a specified string.
+ -s option does not affect line truncation nor column alignment. */
+static int use_col_separator = FALSE;
-/* Character used to separate columns if the the -s flag has been specified. */
-static char column_separator = '\t';
+/* String used to separate columns if the -s option has been specified.
+ Default value with -s is a space. */
+static char *col_sep_string;
+static int col_sep_length = 0;
+static char *column_separator = " ";
/* Number of separator characters waiting to be printed as soon as we
know that we have any input remaining to be printed. */
@@ -423,19 +571,27 @@ static char *header;
static int *clump_buff;
-/* True means we truncate lines longer than chars_per_column. */
-static int truncate_lines = FALSE;
-
/* If nonzero, display usage information and exit. */
static int show_help;
/* If nonzero, print the version on standard output then exit. */
static int show_version;
+/* True means we read the line no. lines_per_body in skip_read
+ called by skip_to_page. That variable controls the coincidence of a
+ "FF set by hand" and "full_page_printed", see above the definition of
+ structure COLUMN. */
+static int last_line = FALSE;
+
+/* If nonzero, print a non-variable date and time with the header
+ -h HEADER using pr test-suite */
+static int test_suite;
+
static struct option const long_options[] =
{
{"help", no_argument, &show_help, 1},
{"version", no_argument, &show_version, 1},
+ {"test", no_argument, &test_suite, 1},
{0, 0, 0, 0}
};
@@ -452,11 +608,66 @@ cols_ready_to_print (void)
n = 0;
for (q = column_vector, i = 0; i < columns; ++q, ++i)
if (q->status == OPEN ||
+ q->status == FF_FOUND || /* With -b: To print a header only */
(storing_columns && q->lines_stored > 0 && q->lines_to_print > 0))
++n;
return n;
}
+/* Estimate first_ / last_page_number
+ using option +FIRST_PAGE:LAST_PAGE */
+
+static void
+first_last_page (char *pages)
+{
+ char *str1;
+
+ if (*pages == ':')
+ {
+ error (0, 0, _("invalid range of page numbers: `%s'"), pages);
+ usage (2);
+ }
+
+ str1 = strchr (pages, ':');
+ if (str1 != NULL)
+ *str1 = '\0';
+
+ {
+ long int tmp_long;
+ if (xstrtol (pages, NULL, 10, &tmp_long, NULL) != LONGINT_OK
+ || tmp_long <= 0 || tmp_long > INT_MAX)
+ error (EXIT_FAILURE, 0, _("invalid starting page number: `%s'"),
+ pages);
+ first_page_number = (int) tmp_long;
+ }
+
+ if (str1 == NULL)
+ return;
+
+ {
+ long int tmp_long;
+ if (xstrtol (str1 + 1, NULL, 10, &tmp_long, NULL) != LONGINT_OK
+ || tmp_long <= 0 || tmp_long > INT_MAX)
+ error (EXIT_FAILURE, 0, _("invalid ending page number: `%s'"),
+ str1 + 1);
+ last_page_number = (int) tmp_long;
+ }
+
+ if (first_page_number > last_page_number)
+ error (EXIT_FAILURE, 0,
+ _("starting page number is larger than ending page number"));
+}
+
+/* Estimate length of col_sep_string with option -s[STRING] */
+
+static void
+separator_string (char *optarg_S)
+{
+ col_sep_length = (int) strlen (optarg_S);
+ col_sep_string = (char *) xmalloc (col_sep_length + 1);
+ strcpy (col_sep_string, optarg_S);
+}
+
int
main (int argc, char **argv)
{
@@ -478,22 +689,16 @@ main (int argc, char **argv)
while (1)
{
c = getopt_long (argc, argv,
- "-0123456789abcde::fFh:i::l:mn::o:rs::tvw:",
+ "-0123456789abcde::fFh:i::jl:mn::N:o:rs::tTvw:",
long_options, (int *) 0);
- if (c == 1) /* Non-option argument. */
+ if (c == 1) /* Non-option argument. */
{
char *s;
s = optarg;
if (*s == '+')
{
++s;
- if (!ISDIGIT (*s))
- {
- error (0, 0, _("`+' requires a numeric argument"));
- usage (2);
- }
- /* FIXME: use strtol */
- first_page_number = atoi (s);
+ first_last_page (s);
}
else
{
@@ -526,7 +731,7 @@ main (int argc, char **argv)
switch (c)
{
- case 0: /* getopt long option */
+ case 0: /* getopt long option */
break;
case 'a':
@@ -564,9 +769,19 @@ main (int argc, char **argv)
/* Could check tab width > 0. */
tabify_output = TRUE;
break;
- case 'l':
- lines_per_page = atoi (optarg);
+ case 'j':
+ join_lines = TRUE;
break;
+ case 'l':
+ {
+ long int tmp_long;
+ if (xstrtol (optarg, NULL, 10, &tmp_long, NULL) != LONGINT_OK
+ || tmp_long <= 0 || tmp_long > INT_MAX)
+ error (EXIT_FAILURE, 0,
+ _("`-l PAGE_LENGTH' invalid number of lines: `%s'"), optarg);
+ lines_per_page = (int) tmp_long;
+ break;
+ }
case 'm':
parallel_files = TRUE;
storing_columns = FALSE;
@@ -577,37 +792,57 @@ main (int argc, char **argv)
getoptarg (optarg, 'n', &number_separator,
&chars_per_number);
break;
+ case 'N':
+ skip_count = FALSE;
+ {
+ long int tmp_long;
+ if (xstrtol (optarg, NULL, 10, &tmp_long, NULL) != LONGINT_OK
+ || tmp_long > INT_MAX)
+ error (EXIT_FAILURE, 0,
+ _("`-N NUMBER' invalid starting line number: `%s'"), optarg);
+ start_line_num = (int) tmp_long;
+ break;
+ }
case 'o':
- chars_per_margin = atoi (optarg);
- break;
+ {
+ long int tmp_long;
+ if (xstrtol (optarg, NULL, 10, &tmp_long, NULL) != LONGINT_OK
+ || tmp_long <= 0 || tmp_long > INT_MAX)
+ error (EXIT_FAILURE, 0,
+ _("`-o MARGIN' invalid line offset: `%s'"), optarg);
+ chars_per_margin = (int) tmp_long;
+ break;
+ }
case 'r':
ignore_failed_opens = TRUE;
break;
case 's':
- use_column_separator = TRUE;
+ use_col_separator = TRUE;
if (optarg)
- {
- char *s;
- s = optarg;
- column_separator = *s;
- if (*++s)
- {
- fprintf (stderr, _("\
-%s: extra characters in the argument to the `-s' option: `%s'\n"),
- program_name, s);
- usage (2);
- }
- }
+ separator_string (optarg);
break;
case 't':
extremities = FALSE;
+ keep_FF = TRUE;
+ break;
+ case 'T':
+ extremities = FALSE;
+ keep_FF = FALSE;
break;
case 'v':
use_esc_sequence = TRUE;
break;
case 'w':
- chars_per_line = atoi (optarg);
- break;
+ truncate_lines = TRUE;
+ {
+ long int tmp_long;
+ if (xstrtol (optarg, NULL, 10, &tmp_long, NULL) != LONGINT_OK
+ || tmp_long <= 0 || tmp_long > INT_MAX)
+ error (EXIT_FAILURE, 0,
+ _("`-w PAGE_WIDTH' invalid column number: `%s'"), optarg);
+ chars_per_line = (int) tmp_long;
+ break;
+ }
default:
usage (2);
break;
@@ -625,13 +860,13 @@ main (int argc, char **argv)
if (parallel_files && explicit_columns)
error (EXIT_FAILURE, 0,
- _("Cannot specify number of columns when printing in parallel."));
+ _("Cannot specify number of columns when printing in parallel."));
if (parallel_files && print_across_flag)
error (EXIT_FAILURE, 0,
- _("Cannot specify both printing across and printing in parallel."));
+ _("Cannot specify both printing across and printing in parallel."));
- for ( ; optind < argc; optind++)
+ for (; optind < argc; optind++)
{
file_names[n_files++] = argv[optind];
}
@@ -648,7 +883,7 @@ main (int argc, char **argv)
else
{
int i;
- for (i=0; i<n_files; i++)
+ for (i = 0; i < n_files; i++)
print_files (1, &file_names[i]);
}
}
@@ -660,7 +895,7 @@ main (int argc, char **argv)
if (ferror (stdout) || fclose (stdout) == EOF)
error (EXIT_FAILURE, errno, _("write error"));
if (failed_opens > 0)
- exit(1);
+ exit (EXIT_FAILURE);
exit (EXIT_SUCCESS);
}
@@ -677,15 +912,16 @@ getoptarg (char *arg, char switch_char, char *character, int *number)
*character = *arg++;
if (*arg)
{
- if (ISDIGIT (*arg))
- *number = atoi (arg);
- else
+ long int tmp_long;
+ if (xstrtol (arg, NULL, 10, &tmp_long, NULL) != LONGINT_OK
+ || tmp_long <= 0 || tmp_long > INT_MAX)
{
- fprintf (stderr, _("\
-%s: extra characters in the argument to the `-%c' option: `%s'\n"),
- program_name, switch_char, arg);
+ error (0, 0,
+ _("`-%c' extra characters or invalid number in the argument: `%s'"),
+ switch_char, arg);
usage (2);
}
+ *number = (int) tmp_long;
}
}
@@ -696,9 +932,18 @@ init_parameters (int number_of_files)
{
int chars_used_by_number = 0;
+ if (use_form_feed)
+ {
+ lines_per_header = 3;
+ lines_per_footer = 0;
+ }
+
lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
if (lines_per_body <= 0)
- extremities = FALSE;
+ {
+ extremities = FALSE;
+ keep_FF = TRUE;
+ }
if (extremities == FALSE)
lines_per_body = lines_per_page;
@@ -713,20 +958,35 @@ init_parameters (int number_of_files)
if (parallel_files)
columns = number_of_files;
+ /* One file, multi columns down: -b option is set to get a consistent
+ formulation with "FF set by hand" in input files. */
+ if (storing_columns)
+ balance_columns = TRUE;
+
/* Tabification is assumed for multiple columns. */
if (columns > 1)
{
- if (!use_column_separator)
- truncate_lines = TRUE;
+ if (!use_col_separator)
+ {
+ col_sep_string = column_separator;
+ col_sep_length = 1;
+ use_col_separator = TRUE;
+ }
+ truncate_lines = TRUE;
untabify_input = TRUE;
tabify_output = TRUE;
}
else
storing_columns = FALSE;
+ /* -j dominates -w in any case */
+ if (join_lines)
+ truncate_lines = FALSE;
+
if (numbered_lines)
{
+ line_count = start_line_num;
if (number_separator == input_tab_char)
{
number_width = chars_per_number +
@@ -742,7 +1002,7 @@ init_parameters (int number_of_files)
}
chars_per_column = (chars_per_line - chars_used_by_number -
- (columns - 1) * chars_per_gutter) / columns;
+ (columns - 1) * col_sep_length) / columns;
if (chars_per_column < 1)
error (EXIT_FAILURE, 0, _("page width too narrow"));
@@ -751,8 +1011,7 @@ init_parameters (int number_of_files)
{
if (number_buff != (char *) 0)
free (number_buff);
- number_buff = (char *)
- xmalloc (2 * chars_per_number * sizeof (char));
+ number_buff = (char *) xmalloc (2 * chars_per_number);
}
/* Pick the maximum between the tab width and the width of an
@@ -769,7 +1028,10 @@ init_parameters (int number_of_files)
With multiple files, each column p has a different p->fp.
With single files, each column p has the same p->fp.
Return 1 if (number_of_files > 0) and no files can be opened,
- 0 otherwise. */
+ 0 otherwise.
+
+ With each column/file p, p->full_page_printed is initialized,
+ see also open_file. */
static int
init_fps (int number_of_files, char **av)
@@ -815,6 +1077,7 @@ init_fps (int number_of_files, char **av)
p->fp = stdin;
have_read_stdin = TRUE;
p->status = OPEN;
+ p->full_page_printed = FALSE;
++total_files;
init_header ("", -1);
}
@@ -826,6 +1089,7 @@ init_fps (int number_of_files, char **av)
p->name = firstname;
p->fp = firstfp;
p->status = OPEN;
+ p->full_page_printed = FALSE;
}
}
files_ready_to_read = total_files;
@@ -846,7 +1110,7 @@ init_funcs (void)
h = chars_per_margin;
- if (use_column_separator)
+ if (!truncate_lines)
h_next = ANYWHERE;
else
{
@@ -859,6 +1123,10 @@ init_funcs (void)
h_next = h + chars_per_column;
}
+ /* Enlarge p->start_position of first column to use the same form of
+ padding_not_printed with all columns. */
+ h = h + col_sep_length;
+
/* This loop takes care of all but the rightmost column. */
for (p = column_vector, i = 1; i < columns; ++p, ++i)
@@ -880,18 +1148,18 @@ init_funcs (void)
p->numbered = numbered_lines && (!parallel_files || i == 1);
p->start_position = h;
- /* If we're using separators, all start_positions are
+ /* If we don't truncate lines, all start_positions are
ANYWHERE, except the first column's start_position when
using a margin. */
- if (use_column_separator)
+ if (!truncate_lines)
{
h = ANYWHERE;
h_next = ANYWHERE;
}
else
{
- h = h_next + chars_per_gutter;
+ h = h_next + col_sep_length;
h_next = h + chars_per_column;
}
}
@@ -915,10 +1183,13 @@ init_funcs (void)
p->start_position = h;
}
-/* Open a file. Return nonzero if successful, zero if failed. */
+/* Open a file. Return nonzero if successful, zero if failed.
+
+ With each file p, p->full_page_printed is initialized,
+ see also init_fps. */
static int
-open_file (char *name, COLUMN *p)
+open_file (char *name, COLUMN * p)
{
if (!strcmp (name, "-"))
{
@@ -939,6 +1210,7 @@ open_file (char *name, COLUMN *p)
return 0;
}
p->status = OPEN;
+ p->full_page_printed = FALSE;
++total_files;
return 1;
}
@@ -949,7 +1221,7 @@ open_file (char *name, COLUMN *p)
the status of all columns in the column list to reflect the close. */
static void
-close_file (COLUMN *p)
+close_file (COLUMN * p)
{
COLUMN *q;
int i;
@@ -988,16 +1260,22 @@ close_file (COLUMN *p)
status of all columns in the column list. */
static void
-hold_file (COLUMN *p)
+hold_file (COLUMN * p)
{
COLUMN *q;
int i;
if (!parallel_files)
for (q = column_vector, i = columns; i; ++q, --i)
- q->status = ON_HOLD;
+ {
+ if (storing_columns)
+ q->status = FF_FOUND;
+ else
+ q->status = ON_HOLD;
+ }
else
p->status = ON_HOLD;
+
p->lines_to_print = 0;
--files_ready_to_read;
}
@@ -1017,6 +1295,9 @@ reset_status (void)
p->status = OPEN;
files_ready_to_read++;
}
+
+ if (storing_columns)
+ files_ready_to_read = 1;
}
/* Print a single file, or multiple files in parallel.
@@ -1049,14 +1330,14 @@ print_files (int number_of_files, char **av)
init_funcs ();
- line_number = 1;
+ line_number = line_count;
while (print_page ())
;
}
-/* Generous estimate of number of characters taken up by "Jun 7 00:08 " and
- "Page NNNNN". */
-#define CHARS_FOR_DATE_AND_PAGE 50
+/* Estimate the number of characters taken up by a short format date and
+ time: "yy-mm-dd HH:MM" and: "Page NNNN". */
+#define CHARS_FOR_DATE_AND_PAGE 23
/* Initialize header information.
If DESC is non-negative, it is a file descriptor open to
@@ -1064,48 +1345,83 @@ print_files (int number_of_files, char **av)
Allocate space for a header string,
Determine the time, insert file name or user-specified string.
-
- It might be nice to have a "blank headers" option, since
- pr -h "" still prints the date and page number. */
+ Make use of a centered header with left-hand-side truncation marked by
+ a '*` in front, if necessary. */
static void
init_header (char *filename, int desc)
{
- int chars_per_header;
+ int chars_per_middle, chars_free, lhs_blanks, rhs_blanks;
char *f = filename;
- char *t, *middle;
+ char *no_middle = "";
+ char *header_text, *fmt, *t_buf;
+ struct tm *tmptr;
struct stat st;
+ char *datim = "- Date/Time --";
+
+ fmt = "%y-%m-%d %H:%M"; /* date/time short format */
if (filename == 0)
f = "";
- /* If parallel files or standard input, use current time. */
- if (desc < 0 || !strcmp (filename, "-") || fstat (desc, &st))
- st.st_mtime = time ((time_t *) 0);
- t = ctime (&st.st_mtime);
+ if (header != (char *) 0)
+ free (header);
+ header = (char *) xmalloc (chars_per_line + 1);
- t[16] = '\0'; /* Mark end of month and time string. */
- t[24] = '\0'; /* Mark end of year string. */
+ if (!standard_header && *custom_header == '\0')
+ sprintf (header, "%s", " "); /* blank line header */
+ else
+ {
+ /* If parallel files or standard input, use current time. */
+ if (desc < 0 || !strcmp (filename, "-") || fstat (desc, &st))
+ st.st_mtime = time ((time_t *) 0);
- middle = standard_header ? f : custom_header;
+ {
+ size_t t_buf_size = 15;
+ t_buf = (char *) xmalloc (t_buf_size);
+ tmptr = localtime (&st.st_mtime);
+ strftime (t_buf, t_buf_size, fmt, tmptr);
+ }
- chars_per_header = strlen (middle) + CHARS_FOR_DATE_AND_PAGE + 1;
- if (header != (char *) 0)
- free (header);
- header = (char *) xmalloc (chars_per_header * sizeof (char));
+ chars_per_middle = chars_per_line - CHARS_FOR_DATE_AND_PAGE;
+ if (chars_per_middle < 3)
+ {
+ header_text = no_middle; /* Nothing free for a heading */
+ lhs_blanks = 1;
+ rhs_blanks = 1;
+ }
+ else
+ {
+ header_text = standard_header ? f : custom_header;
+ chars_free = chars_per_middle - (int) strlen (header_text);
+ if (chars_free > 1)
+ {
+ lhs_blanks = chars_free / 2; /* text not truncated */
+ rhs_blanks = chars_free - lhs_blanks;
+ }
+ else
+ { /* lhs truncation */
+ header_text = header_text - chars_free + 2;
+ *header_text = '*';
+ lhs_blanks = 1;
+ rhs_blanks = 1;
+ }
+ }
- sprintf (header, _("%s %s %s Page"), &t[4], &t[20], middle);
+ sprintf (header, _("%s%*s%s%*sPage"), (test_suite ? datim : t_buf),
+ lhs_blanks, " ", header_text, rhs_blanks, " ");
+ }
}
/* Set things up for printing a page
Scan through the columns ...
- Determine which are ready to print
- (i.e., which have lines stored or open files)
- Set p->lines_to_print appropriately
- (to p->lines_stored if we're storing, or lines_per_body
- if we're reading straight from the file)
- Keep track of this total so we know when to stop printing */
+ Determine which are ready to print
+ (i.e., which have lines stored or open files)
+ Set p->lines_to_print appropriately
+ (to p->lines_stored if we're storing, or lines_per_body
+ if we're reading straight from the file)
+ Keep track of this total so we know when to stop printing */
static void
init_page (void)
@@ -1148,16 +1464,37 @@ init_page (void)
p->lines_to_print = 0;
}
+/* Align empty columns and print separators.
+ Empty columns will be formed by files with status ON_HOLD or CLOSED
+ when printing multiple files in parallel. */
+
+static void
+align_column (COLUMN * p)
+{
+ padding_not_printed = p->start_position;
+ if (padding_not_printed - col_sep_length > 0)
+ {
+ pad_across_to (padding_not_printed - col_sep_length);
+ padding_not_printed = ANYWHERE;
+ }
+
+ if (use_col_separator)
+ print_sep_string ();
+
+ if (p->numbered)
+ number (p);
+}
+
/* Print one page.
As long as there are lines left on the page and columns ready to print,
- Scan across the column list
- if the column has stored lines or the file is open
- pad to the appropriate spot
- print the column
+ Scan across the column list
+ if the column has stored lines or the file is open
+ pad to the appropriate spot
+ print the column
pad the remainder of the page with \n or \f as requested
reset the status of all files -- any files which where on hold because
- of formfeeds are now put back into the lineup. */
+ of formfeeds are now put back into the lineup. */
static int
print_page (void)
@@ -1197,28 +1534,49 @@ print_page (void)
spaces_not_printed = 0;
separators_not_printed = 0;
pad_vertically = FALSE;
+ align_empty_cols = FALSE;
+ empty_line = TRUE;
for (j = 1, p = column_vector; j <= columns; ++j, ++p)
{
input_position = 0;
- if (p->lines_to_print > 0)
+ if (p->lines_to_print > 0 || p->status == FF_FOUND)
{
+ FF_only = FALSE;
padding_not_printed = p->start_position;
-
if (!(p->print_func) (p))
read_rest_of_line (p);
pv |= pad_vertically;
- if (use_column_separator)
- ++separators_not_printed;
-
--p->lines_to_print;
if (p->lines_to_print <= 0)
{
if (cols_ready_to_print () <= 0)
break;
}
+
+ /* File p changed its status to ON_HOLD or CLOSED */
+ if (parallel_files && p->status != OPEN)
+ {
+ if (empty_line)
+ align_empty_cols = TRUE;
+ else if (p->status == CLOSED ||
+ (p->status == ON_HOLD && FF_only))
+ align_column (p);
+ }
+ }
+ else if (parallel_files)
+ {
+ /* File status ON_HOLD or CLOSED */
+ if (empty_line)
+ align_empty_cols = TRUE;
+ else
+ align_column (p);
}
+
+ /* We need it also with an empty column */
+ if (use_col_separator)
+ ++separators_not_printed;
}
if (pad_vertically)
@@ -1234,10 +1592,23 @@ print_page (void)
}
}
+ if (lines_left_on_page == 0)
+ for (j = 1, p = column_vector; j <= columns; ++j, ++p)
+ if (p->status == OPEN)
+ p->full_page_printed = TRUE;
+
pad_vertically = pv;
if (pad_vertically && extremities)
pad_down (lines_left_on_page + lines_per_footer);
+ else if (keep_FF && print_a_FF)
+ {
+ putchar ('\f');
+ print_a_FF = FALSE;
+ }
+
+ if (last_page_number && page_number > last_page_number)
+ return FALSE; /* Stop printing with LAST_PAGE */
reset_status (); /* Change ON_HOLD to OPEN. */
@@ -1248,6 +1619,8 @@ print_page (void)
This is necessary when printing multiple columns from a single file.
Lines are stored consecutively in buff, separated by '\0'.
+
+ The following doesn't apply any longer - any tuning possible?
(We can't use a fixed offset since with the '-s' flag lines aren't
truncated.)
@@ -1272,22 +1645,22 @@ init_store_cols (void)
if (buff != (char *) 0)
free (buff);
- buff_allocated = use_column_separator ? 2 * chars_if_truncate
+ buff_allocated = use_col_separator ? 2 * chars_if_truncate
: chars_if_truncate; /* Tune this. */
- buff = (char *) xmalloc (buff_allocated * sizeof (char));
+ buff = (char *) xmalloc (buff_allocated);
}
/* Store all but the rightmost column.
(Used when printing a single file in multiple downward columns)
For each column
- set p->current_line to be the index in line_vector of the
- first line in the column
- For each line in the column
- store the line in buff
- add to line_vector the index of the line's first char
- buff_start is the index in buff of the first character in the
- current line. */
+ set p->current_line to be the index in line_vector of the
+ first line in the column
+ For each line in the column
+ store the line in buff
+ add to line_vector the index of the line's first char
+ buff_start is the index in buff of the first character in the
+ current line. */
static void
store_columns (void)
@@ -1375,7 +1748,7 @@ store_char (int c)
}
static void
-number (COLUMN *p)
+number (COLUMN * p)
{
int i;
char *s;
@@ -1440,7 +1813,7 @@ pad_down (int lines)
to print or store its characters. */
static void
-read_rest_of_line (COLUMN *p)
+read_rest_of_line (COLUMN * p)
{
register int c;
FILE *f = p->fp;
@@ -1449,6 +1822,74 @@ read_rest_of_line (COLUMN *p)
{
if (c == '\f')
{
+ if ((c = getc (f)) != '\n')
+ ungetc (c, f);
+ if (keep_FF)
+ print_a_FF = TRUE;
+ hold_file (p);
+ break;
+ }
+ else if (c == EOF)
+ {
+ close_file (p);
+ break;
+ }
+ }
+}
+
+/* Read a line with skip_to_page.
+
+ Read from the current column's file until an end of line is
+ hit. Used when we read full lines to skip pages.
+ With skip_to_page we have to check for FF-coincidence which is done
+ in function read_line otherwise.
+ Count lines of skipped pages to find the line number of 1st page
+ printed relative to 1st line of input file (start_line_num). */
+
+static void
+skip_read (COLUMN * p, int column_number)
+{
+ register int c;
+ FILE *f = p->fp;
+ int i, single_ff = FALSE;
+ COLUMN *q;
+
+ /* Read 1st character in a line or any character succeeding a FF */
+ if ((c = getc (f)) == '\f' && p->full_page_printed)
+ /* A FF-coincidence with a previous full_page_printed.
+ To avoid an additional empty page, eliminate the FF */
+ if ((c = getc (f)) == '\n')
+ c = getc (f);
+
+ p->full_page_printed = FALSE;
+
+ /* 1st character a FF means a single FF without any printable
+ characters. Don't count it as a line with -n option. */
+ if (c == '\f')
+ single_ff = TRUE;
+
+ /* Preparing for a FF-coincidence: Maybe we finish that page
+ without a FF found */
+ if (last_line)
+ p->full_page_printed = TRUE;
+
+ while (c != '\n')
+ {
+ if (c == '\f')
+ {
+ /* No FF-coincidence possible,
+ no catching up of a FF-coincidence with next page */
+ if (last_line)
+ {
+ if (!parallel_files)
+ for (q = column_vector, i = columns; i; ++q, --i)
+ q->full_page_printed = FALSE;
+ else
+ p->full_page_printed = FALSE;
+ }
+
+ if ((c = getc (f)) != '\n')
+ ungetc (c, f);
hold_file (p);
break;
}
@@ -1457,7 +1898,12 @@ read_rest_of_line (COLUMN *p)
close_file (p);
break;
}
+ c = getc (f);
}
+
+ if (skip_count)
+ if ((!parallel_files || column_number == 1) && !single_ff)
+ ++line_count;
}
/* If we're tabifying output,
@@ -1474,7 +1920,7 @@ print_white_space (void)
register int goal = h_old + spaces_not_printed;
while (goal - h_old > 1
- && (h_new = pos_after_tab (chars_per_output_tab, h_old)) <= goal)
+ && (h_new = pos_after_tab (chars_per_output_tab, h_old)) <= goal)
{
putchar (output_tab_char);
h_old = h_new;
@@ -1489,20 +1935,32 @@ print_white_space (void)
/* Print column separators.
We keep a count until we know that we'll be printing a line,
- then print_separators() is called. */
+ then print_sep_string() is called. */
static void
-print_separators (void)
+print_sep_string ()
{
+ char *s;
+ int l = col_sep_length;
+
+ s = col_sep_string;
+
+ if (spaces_not_printed > 0)
+ print_white_space ();
+
for (; separators_not_printed > 0; --separators_not_printed)
- print_char (column_separator);
+ {
+ while (l-- > 0)
+ putchar (*s++);
+ output_position += col_sep_length;
+ }
}
/* Print (or store, depending on p->char_func) a clump of N
characters. */
static void
-print_clump (COLUMN *p, int n, int *clump)
+print_clump (COLUMN * p, int n, int *clump)
{
while (n--)
(p->char_func) (*clump++);
@@ -1510,6 +1968,8 @@ print_clump (COLUMN *p, int n, int *clump)
/* Print a character.
+ Update the following comment: process-char hasn't been used any
+ longer.
If we're tabifying, all tabs have been converted to spaces by
process_char(). Keep a count of consecutive spaces, and when
a nonspace is encountered, call print_white_space() to print the
@@ -1550,12 +2010,23 @@ skip_to_page (int page)
for (n = 1; n < page; ++n)
{
- for (i = 1; i <= lines_per_body; ++i)
+ for (i = 1; i < lines_per_body; ++i)
{
for (j = 1, p = column_vector; j <= columns; ++j, ++p)
- read_rest_of_line (p);
+ if (p->status == OPEN)
+ skip_read (p, j);
}
+ last_line = TRUE;
+ for (j = 1, p = column_vector; j <= columns; ++j, ++p)
+ if (p->status == OPEN)
+ skip_read (p, j);
+
+ if (storing_columns) /* change FF_FOUND to ON_HOLD */
+ for (j = 1, p = column_vector; j <= columns; ++j, ++p)
+ p->status = ON_HOLD;
+
reset_status ();
+ last_line = FALSE;
}
return files_ready_to_read > 0;
}
@@ -1575,7 +2046,10 @@ print_header (void)
pad_across_to (chars_per_margin);
print_white_space ();
- fprintf (stdout, "%s %d\n\n\n", header, page_number++);
+ if (!standard_header && *custom_header == '\0')
+ fprintf (stdout, "%s\n\n\n", header);
+ else
+ fprintf (stdout, "%s%5d\n\n\n", header, page_number++);
print_a_header = FALSE;
output_position = 0;
@@ -1587,37 +2061,57 @@ print_header (void)
(We may hit EOF, \n, or \f)
Once we know we have a line,
- set pad_vertically = TRUE, meaning it's safe
- to pad down at the end of the page, since we do have a page.
- print a header if needed.
- pad across to padding_not_printed if needed.
- print any separators which need to be printed.
- print a line number if it needs to be printed.
+ set pad_vertically = TRUE, meaning it's safe
+ to pad down at the end of the page, since we do have a page.
+ print a header if needed.
+ pad across to padding_not_printed if needed.
+ print any separators which need to be printed.
+ print a line number if it needs to be printed.
Print the clump which corresponds to the first character.
Enter a loop and keep printing until an end of line condition
- exists, or until we exceed chars_per_column.
+ exists, or until we exceed chars_per_column.
Return FALSE if we exceed chars_per_column before reading
- an end of line character, TRUE otherwise. */
+ an end of line character, TRUE otherwise. */
static int
-read_line (COLUMN *p)
+read_line (COLUMN * p)
{
register int c, chars;
int last_input_position;
+ int j, k;
+ COLUMN *q;
-#ifdef lint /* Suppress `used before initialized' warning. */
+/* Suppress `used before initialized' warning. */
+#ifdef lint
chars = 0;
#endif
+ /* read 1st character in each line or any character succeeding a FF: */
c = getc (p->fp);
last_input_position = input_position;
+
+ if (c == '\f' && p->full_page_printed)
+ if ((c = getc (p->fp)) == '\n')
+ c = getc (p->fp);
+ p->full_page_printed = FALSE;
+
switch (c)
{
case '\f':
+ if ((c = getc (p->fp)) != '\n')
+ ungetc (c, p->fp);
+ FF_only = TRUE;
+ if (print_a_header && !storing_columns)
+ {
+ pad_vertically = TRUE;
+ print_header ();
+ }
+ else if (keep_FF)
+ print_a_FF = TRUE;
hold_file (p);
return TRUE;
case EOF:
@@ -1639,22 +2133,41 @@ read_line (COLUMN *p)
{
pad_vertically = TRUE;
- if (print_a_header)
+ if (print_a_header && !storing_columns)
print_header ();
- if (padding_not_printed != ANYWHERE)
+ if (parallel_files && align_empty_cols)
{
- pad_across_to (padding_not_printed);
+ /* We have to align empty columns at the beginning of a line. */
+ k = separators_not_printed;
+ separators_not_printed = 0;
+ for (j = 1, q = column_vector; j <= k; ++j, ++q)
+ {
+ align_column (q);
+ separators_not_printed += 1;
+ }
+ padding_not_printed = p->start_position;
+ if (truncate_lines)
+ spaces_not_printed = chars_per_column;
+ else
+ spaces_not_printed = 0;
+ align_empty_cols = FALSE;
+ }
+
+ if (padding_not_printed - col_sep_length > 0)
+ {
+ pad_across_to (padding_not_printed - col_sep_length);
padding_not_printed = ANYWHERE;
}
- if (use_column_separator)
- print_separators ();
+ if (use_col_separator)
+ print_sep_string ();
}
if (p->numbered)
number (p);
+ empty_line = FALSE;
if (c == '\n')
return TRUE;
@@ -1669,6 +2182,10 @@ read_line (COLUMN *p)
case '\n':
return TRUE;
case '\f':
+ if ((c = getc (p->fp)) != '\n')
+ ungetc (c, p->fp);
+ if (keep_FF)
+ print_a_FF = TRUE;
hold_file (p);
return TRUE;
case EOF:
@@ -1690,16 +2207,24 @@ read_line (COLUMN *p)
/* Print a line from buff.
- If this function has been called, we know we have something to
- print. Therefore we set pad_vertically to TRUE, print
- a header if necessary, pad across if necessary, and print
- separators if necessary.
+ If this function has been called, we know we have "something to
+ print". But it remains to be seen whether we have a real text page
+ or an empty page (a single form feed) with/without a header only.
+ Therefore first we set pad_vertically to TRUE and print a header
+ if necessary.
+ If FF_FOUND and we are using -t|-T option we omit any newline by
+ setting pad_vertically to FALSE (see print_page).
+ Otherwise we pad across if necessary, print separators if necessary
+ and text of COLUMN *p.
Return TRUE, meaning there is no need to call read_rest_of_line. */
static int
-print_stored (COLUMN *p)
+print_stored (COLUMN * p)
{
+ COLUMN *q;
+ int i;
+
int line = p->current_line++;
register char *first = &buff[line_vector[line]];
register char *last = &buff[line_vector[line + 1]];
@@ -1709,20 +2234,36 @@ print_stored (COLUMN *p)
if (print_a_header)
print_header ();
- if (padding_not_printed != ANYWHERE)
+ if (p->status == FF_FOUND)
+ {
+ for (i = 1, q = column_vector; i <= columns; ++i, ++q)
+ q->status = ON_HOLD;
+ if (column_vector->lines_to_print <= 0)
+ {
+ if (!extremities)
+ pad_vertically = FALSE;
+ return TRUE; /* print a header only */
+ }
+ }
+
+ if (padding_not_printed - col_sep_length > 0)
{
- pad_across_to (padding_not_printed);
+ pad_across_to (padding_not_printed - col_sep_length);
padding_not_printed = ANYWHERE;
}
- if (use_column_separator)
- print_separators ();
+ if (use_col_separator)
+ print_sep_string ();
while (first != last)
print_char (*first++);
if (spaces_not_printed == 0)
- output_position = p->start_position + end_vector[line];
+ {
+ output_position = p->start_position + end_vector[line];
+ if (p->start_position - col_sep_length == chars_per_margin)
+ output_position -= col_sep_length;
+ }
return TRUE;
}
@@ -1855,33 +2396,54 @@ usage (int status)
Usage: %s [OPTION]... [FILE]...\n\
"),
program_name);
+
printf (_("\
Paginate or columnate FILE(s) for printing.\n\
\n\
- +PAGE begin printing with page PAGE\n\
- -COLUMN produce COLUMN-column output and print columns down\n\
- -a print columns across rather than down\n\
- -b balance columns on the last page\n\
+ +FIRST_PAGE[:LAST_PAGE]
+ begin [stop] printing with page FIRST_[LAST_]PAGE\n\
+ -COLUMN produce COLUMN-column output and print columns down,\n\
+ unless -a is used. Balance number of lines in the\n\
+ columns on each page.\n\
+ -a print columns across rather than down, used together\n\
+ with -COLUMN\n\
-c use hat notation (^G) and octal backslash notation\n\
-d double space the output\n\
-e[CHAR[WIDTH]] expand input CHARs (TABs) to tab WIDTH (8)\n\
- -f, -F simulate formfeed with newlines on output\n\
- -h HEADER use HEADER instead of filename in page headers\n\
+ -F, -f use form feeds instead of newlines to separate pages\n\
+ (by a 3-line page header with -f or a 5-line header\n\
+ and trailer without -f)\n\
+ -h HEADER use a centered HEADER instead of filename in page headers\n\
+ with long headers left-hand-side truncation may occur\n\
+ -h \"\" prints a blank line. Don't use -h\"\"\n\
-i[CHAR[WIDTH]] replace spaces with CHARs (TABs) to tab WIDTH (8)\n\
+ -j merge full lines, turns off -w line truncation, no column\n\
+ alignment, -s[STRING] sets separators\n\
-l PAGE_LENGTH set the page length to PAGE_LENGTH (66) lines\n\
- -m print all files in parallel, one in each column\n\
+ (default number of lines of text 56, with -f 63)\n\
+ -m print all files in parallel, one in each column,\n\
+ truncate lines, but join lines of full length with -j\n\
-n[SEP[DIGITS]] number lines, use DIGITS (5) digits, then SEP (TAB)\n\
+ default counting starts with 1st line of input file\n\
+ -N NUMBER start counting with NUMBER at 1st line of first\n\
+ page printed (see +FIRST_PAGE)\n\
-o MARGIN offset each line with MARGIN spaces (do not affect -w)\n\
-r inhibit warning when a file cannot be opened\n\
- -s[SEP] separate columns by character SEP (TAB)\n\
- -t inhibit 5-line page headers and trailers\n\
+ -s[STRING] separate columns by an optional STRING\n\
+ don't use -s \"STRING\" \n\
+ without -s: default sep. \'space\' used, same as -s\" \"\n\
+ -s only: no separator used, same as -s\"\" \n\
+ -t inhibit page headers and trailers\n\
+ -T inhibit page headers and trailers, eliminate any page\n\
+ layout by form feeds set in input files\n\
-v use octal backslash notation\n\
- -w PAGE_WIDTH set page width to PAGE_WIDTH (72) columns\n\
- --help display this help and exit\n\
- --version output version information and exit\n\
+ -w PAGE_WIDTH set page width to PAGE_WIDTH (72) columns, truncate\n\
+ lines (see also -j option)\n\
+ --help display this help and exit\n\
+ --version output version information and exit\n\
\n\
--t implied by -l N when N < 10. Without -s, columns are separated by\n\
-spaces. With no FILE, or when FILE is -, read standard input.\n\
+-T implied by -l nn when nn <= 10 or <= 3 with -f. With no FILE, or when\n\
+FILE is -, read standard input.\n\
"));
puts (_("\nReport bugs to textutils-bugs@gnu.ai.mit.edu"));
}