Remove old-style xmalloc and xrealloc decls.
[platform/upstream/coreutils.git] / src / pr.c
1 /* pr -- convert text files for printing.
2    Copyright (C) 88, 91, 95, 96, 1997 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 /*  Author: Pete TerMaat.  */
19 \f
20 /* Things to watch: Sys V screws up on ...
21    pr -n -3 -s: /usr/dict/words
22    pr -m -o10 -n /usr/dict/words{,,,}
23    pr -6 -a -n -o5 /usr/dict/words
24
25    Ideas:
26
27    Keep a things_to_do list of functions to call when we know we have
28    something to print.  Cleaner than current series of checks.
29
30    Improve the printing of control prefixes.
31
32
33    Options:
34
35    +FIRST_PAGE[:LAST_PAGE]
36                 begin [stop] printing with page FIRST_[LAST_]PAGE
37
38    -COLUMN      Produce output that is COLUMN columns wide and print
39                 columns down.
40                 Balance columns on the last page is automatically set.
41
42    -a           Print columns across rather than down.  The input
43                 one
44                 two
45                 three
46                 four
47                 will be printed as
48                 one     two     three
49                 four
50
51    -b           Balance columns on the last page.
52                 -b is no longer an independent option. It's always used
53                 together with -COLUMN (unless -a is used) to get a
54                 consistent formulation with "FF set by hand" in input
55                 files. Each formfeed found terminates the number of lines
56                 to be read with the actual page. The situation for
57                 printing columns down is equivalent to that on the last
58                 page. So we need a balancing.
59
60                 We do not yet eliminate source text dealing with -COLUMN
61                 only. Tune this if it proved to be a satisfactory
62                 procedure.
63
64                 Keeping -b as an underground option guarantees some
65                 downward compatibility. Utilities using pr with -b
66                 (a most frequently used form) still work as usual.
67
68    -c           Print unprintable characters as control prefixes.
69                 Control-g is printed as ^G.
70
71    -d           Double space the output.
72
73    -e[c[k]]     Expand tabs to spaces on input.  Optional argument C
74                 is the input tab character. (Default is `\t'.)  Optional
75                 argument K is the input tab character's width.  (Default is 8.)
76
77    -F
78    -f           Use formfeeds instead of newlines to separate pages.
79                 A three line HEADER is used, no TRAILER (without -f
80                 both HEADER and TRAILER are made of five lines).
81
82    -h HEADER    Replace the filename in the header with the string HEADER.
83                 Checking and left-hand-side truncation of the length of the
84                 standard and custom header string. A centered header is used.
85                 The format of date and time has been shortened
86                 to  yy-mm-dd HH:MM  to give place to a maximal filename
87                 information.
88                 -h ""  now prints a blank line header. -h"" shows an error.
89
90    -i[c[k]]     Replace spaces with tabs on output.  Optional argument
91                 C is the output tab character.  (Default is `\t'.)  Optional
92                 argument K is the output tab character's width.  (Default
93                 is 8.)
94
95   -j            Merge full lines, turns off -w line truncation, no column
96                 alignment, -s[STRING] sets separators, works with all
97                 column options (-COLUMN | -a -COLUMN | -m).
98
99    -l lines     Set the page length to LINES.  Default is 66.
100
101    -m           Print files in parallel; pad_across_to align columns;
102                 truncate lines and print separator strings;
103                 Do it also with empty columns to get a continuous line
104                 numbering and column marking by separators throughout
105                 the whole merged file.
106
107                 Empty pages in some input files produce empty columns
108                 [marked by separators] in the common pages. Completely
109                 empty common pages show no column separators at all.
110
111                 The layout of a merged page is ruled by the largest form
112                 feed distance of the single pages at that page. Shorter
113                 columns will be filled up with empty lines.
114
115                 Together with -j option join lines of full length and
116                 in addition set separators when -s option is used.
117
118    -n[c[k]]     Precede each column with a line number.
119                 (With parallel files, precede each line with a line
120                 number.)  Optional argument C is the character to print
121                 after each number.  (Default `\t'.)  Optional argument
122                 k is the number of digits per line number.  (Default 5.)
123                 Default counting starts with 1st line of input file.
124
125   -N number     Start counting with  number  at 1st line of first page
126                 printed.
127
128    -o offset    Offset each line with a margin OFFSET spaces wide.
129                 Total page width is the size of this offset plus the
130                 width set with `-w'.
131
132    -r           Ignore files that can't be opened.
133
134   -s[STRING]    Separate columns by any string STRING.
135                 Don't use -s "STRING".
136                 without -s: Default separator `TAB' with -j and `space'
137                 otherwise (same as -s\" \"),
138                 with -s only: no separator is used, same as -s"".
139                 Quotes should be used with blanks and some shell active
140                 characters.
141
142    -t           Do not print headers or footers but retain form feeds
143                 set in input files (some page layout is not changed).
144
145    -T           Do not print headers or footers, eliminate form feeds
146                 in input files.
147
148    -v           Print unprintable characters as escape sequences.
149                 Control-G becomes \007.
150
151    -w width     Set the page width to WIDTH characters.
152                 (In pr versions newer than 1.14 -s option does no longer
153                 affect -w option.)
154
155                 With/without  -w width  the header line is truncated.
156                 Default is 72 characters.
157                 With  -w width  text lines will be truncated, unless -j is
158                 used. Together with one of the column options
159                 (-COLUMN| -a -COLUMN| -m) column alignment is used.
160                 Without  -w PAGE_WIDTH
161                 - but with one of the column options default truncation of
162                   72 characters is used (to keep downward compatibility
163                   and to simplify most frequently met column tasks).
164                   Column alignment and column separators are used.
165                 - and without any of the column options no line truncation
166                   is used (to keep downward compatibility and to meet most
167                   frequent tasks). That's equivalent to  -w 72 -j .
168 */
169 \f
170
171 #include <config.h>
172
173 #include <stdio.h>
174 #include <getopt.h>
175 #include <sys/types.h>
176 #include <time.h>
177 #include "system.h"
178 #include "error.h"
179 #include "xstrtol.h"
180
181 #if HAVE_LIMITS_H
182 # include <limits.h>
183 #endif
184
185 #ifndef UINT_MAX
186 # define UINT_MAX ((unsigned int) ~(unsigned int) 0)
187 #endif
188
189 #ifndef INT_MAX
190 # define INT_MAX ((int) (UINT_MAX >> 1))
191 #endif
192
193 #ifndef TRUE
194 # define TRUE   1
195 # define FALSE  0
196 #endif
197
198 /* Used with start_position in the struct COLUMN described below.
199    If start_position == ANYWHERE, we aren't truncating columns and
200    can begin printing a column anywhere.  Otherwise we must pad to
201    the horizontal position start_position. */
202 #define ANYWHERE        0
203
204 /* Each column has one of these structures allocated for it.
205    If we're only dealing with one file, fp is the same for all
206    columns.
207
208    The general strategy is to spend time setting up these column
209    structures (storing columns if necessary), after which printing
210    is a matter of flitting from column to column and calling
211    print_func.
212
213    Parallel files, single files printing across in multiple
214    columns, and single files printing down in multiple columns all
215    fit the same printing loop.
216
217    print_func           Function used to print lines in this column.
218                         If we're storing this column it will be
219                         print_stored(), Otherwise it will be read_line().
220
221    char_func            Function used to process characters in this column.
222                         If we're storing this column it will be store_char(),
223                         otherwise it will be print_char().
224
225    current_line         Index of the current entry in line_vector, which
226                         contains the index of the first character of the
227                         current line in buff[].
228
229    lines_stored         Number of lines in this column which are stored in
230                         buff.
231
232    lines_to_print       If we're storing this column, lines_to_print is
233                         the number of stored_lines which remain to be
234                         printed.  Otherwise it is the number of lines
235                         we can print without exceeding lines_per_body.
236
237    start_position       The horizontal position we want to be in before we
238                         print the first character in this column.
239
240    numbered             True means precede this column with a line number. */
241
242 struct COLUMN
243   {
244     FILE *fp;                   /* Input stream for this column. */
245     char *name;                 /* File name. */
246     enum
247       {
248         OPEN,
249         FF_FOUND,               /* used with -b option, set with \f, changed
250                                    to ON_HOLD after print_header */
251         ON_HOLD,                /* Hit a form feed. */
252         CLOSED
253       }
254     status;                     /* Status of the file pointer. */
255     int (*print_func) ();       /* Func to print lines in this col. */
256     void (*char_func) ();       /* Func to print/store chars in this col. */
257     int current_line;           /* Index of current place in line_vector. */
258     int lines_stored;           /* Number of lines stored in buff. */
259     int lines_to_print;         /* No. lines stored or space left on page. */
260     int start_position;         /* Horizontal position of first char. */
261     int numbered;
262     int full_page_printed;      /* True means printed without a FF found. */
263
264     /* p->full_page_printed  controls a special case of "FF set by hand":
265        True means a full page has been printed without FF found. To avoid an
266        additional empty page we have to ignore a FF immediately following in
267        the next line. */
268   };
269
270 typedef struct COLUMN COLUMN;
271
272 #define NULLCOL (COLUMN *)0
273
274 static int char_to_clump __P ((int c));
275 static int read_line __P ((COLUMN *p));
276 static int print_page __P ((void));
277 static int print_stored __P ((COLUMN *p));
278 static int open_file __P ((char *name, COLUMN *p));
279 static int skip_to_page __P ((int page));
280 static void print_header __P ((void));
281 static void pad_across_to __P ((int position));
282 static void add_line_number __P ((COLUMN *p));
283 static void getoptarg __P ((char *arg, char switch_char, char *character,
284                             int *number));
285 static void usage __P ((int status));
286 static void print_files __P ((int number_of_files, char **av));
287 static void init_parameters __P ((int number_of_files));
288 static void init_header __P ((char *filename, int desc));
289 static void init_store_cols __P ((void));
290 static void store_columns __P ((void));
291 static void balance __P ((int total_stored));
292 static void store_char __P ((int c));
293 static void pad_down __P ((int lines));
294 static void read_rest_of_line __P ((COLUMN *p));
295 static void skip_read __P ((COLUMN *p, int column_number));
296 static void print_char __P ((int c));
297 static void cleanup __P ((void));
298 static void first_last_page __P ((char *pages));
299 static void print_sep_string __P ((void));
300 static void separator_string __P ((const char *optarg_S));
301
302 /* The name under which this program was invoked. */
303 char *program_name;
304
305 /* All of the columns to print.  */
306 static COLUMN *column_vector;
307
308 /* When printing a single file in multiple downward columns,
309    we store the leftmost columns contiguously in buff.
310    To print a line from buff, get the index of the first character
311    from line_vector[i], and print up to line_vector[i + 1]. */
312 static char *buff;
313
314 /* Index of the position in buff where the next character
315    will be stored. */
316 static int buff_current;
317
318 /* The number of characters in buff.
319    Used for allocation of buff and to detect overflow of buff. */
320 static int buff_allocated;
321
322 /* Array of indices into buff.
323    Each entry is an index of the first character of a line.
324    This is used when storing lines to facilitate shuffling when
325    we do column balancing on the last page. */
326 static int *line_vector;
327
328 /* Array of horizonal positions.
329    For each line in line_vector, end_vector[line] is the horizontal
330    position we are in after printing that line.  We keep track of this
331    so that we know how much we need to pad to prepare for the next
332    column. */
333 static int *end_vector;
334
335 /* (-m) True means we're printing multiple files in parallel. */
336 static int parallel_files = FALSE;
337
338 /* (-m) True means a line starts with some empty columns (some files
339    already CLOSED or ON_HOLD) which we have to align. */
340 static int align_empty_cols;
341
342 /* (-m) True means we have not yet found any printable column in a line.
343    align_empty_cols = TRUE  has to be maintained. */
344 static int empty_line;
345
346 /* (-m) False means printable column output precedes a form feed found.
347    Column align is done only once. No additional action with that form
348    feed.
349    True means we found only a form feed in a column. Maybe we have to do
350    some column align with that form feed. */
351 static int FF_only;
352
353 /* (-[0-9]+) True means we're given an option explicitly specifying
354    number of columns.  Used to detect when this option is used with -m. */
355 static int explicit_columns = FALSE;
356
357 /* (-t|-T) False means we aren't printing headers and footers. */
358 static int extremities = TRUE;
359
360 /* (-t) True means we retain all FF set by hand in input files.
361    False is set with -T option. */
362 static int keep_FF = FALSE;
363 static int print_a_FF = FALSE;
364
365 /* True means we need to print a header as soon as we know we've got input
366    to print after it. */
367 static int print_a_header;
368
369 /* (-h) True means we're using the standard header rather than a
370    customized one specified by the -h flag. */
371 static int standard_header = TRUE;
372
373 /* (-f) True means use formfeeds instead of newlines to separate pages. */
374 static int use_form_feed = FALSE;
375
376 /* True means we have read the standard input. */
377 static int have_read_stdin = FALSE;
378
379 /* True means the -a flag has been given. */
380 static int print_across_flag = FALSE;
381
382 /* True means we're printing one file in multiple (>1) downward columns. */
383 static int storing_columns = TRUE;
384
385 /* (-b) True means balance columns on the last page as Sys V does. */
386 /* That's no longer an independent option. With storing_columns = TRUE
387    balance_columns = TRUE is used too (s. function init_parameters).
388    We get a consistent formulation with "FF set by hand" in input files. */
389 static int balance_columns = FALSE;
390
391 /* (-l) Number of lines on a page, including header and footer lines. */
392 static int lines_per_page = 66;
393
394 /* Number of lines in the header and footer can be reset to 0 using
395    the -t flag. */
396 static int lines_per_header = 5;
397 static int lines_per_body;
398 static int lines_per_footer = 5;
399
400 /* (-w) Width in characters of the page.  Does not include the width of
401    the margin. */
402 static int chars_per_line = 72;
403
404 /* (-w) True means we truncate lines longer than chars_per_column. */
405 static int truncate_lines = FALSE;
406
407 /* (-j) True means we join lines without any line truncation. -j
408    dominates -w option. */
409 static int join_lines = FALSE;
410
411 /* Number of characters in a column.  Based on col_sep_length and
412    page width. */
413 static int chars_per_column;
414
415 /* (-e) True means convert tabs to spaces on input. */
416 static int untabify_input = FALSE;
417
418 /* (-e) The input tab character. */
419 static char input_tab_char = '\t';
420
421 /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
422    where the leftmost column is 1. */
423 static int chars_per_input_tab = 8;
424
425 /* (-i) True means convert spaces to tabs on output. */
426 static int tabify_output = FALSE;
427
428 /* (-i) The output tab character. */
429 static char output_tab_char = '\t';
430
431 /* (-i) The width of the output tab. */
432 static int chars_per_output_tab = 8;
433
434 /* Keeps track of pending white space.  When we hit a nonspace
435    character after some whitespace, we print whitespace, tabbing
436    if necessary to get to output_position + spaces_not_printed. */
437 static int spaces_not_printed;
438
439 /* (-o) Number of spaces in the left margin (tabs used when possible). */
440 static int chars_per_margin = 0;
441
442 /* Position where the next character will fall.
443    Leftmost position is 0 + chars_per_margin.
444    Rightmost position is chars_per_margin + chars_per_line - 1.
445    This is important for converting spaces to tabs on output. */
446 static int output_position;
447
448 /* Horizontal position relative to the current file.
449    (output_position depends on where we are on the page;
450    input_position depends on where we are in the file.)
451    Important for converting tabs to spaces on input. */
452 static int input_position;
453
454 /* Count number of failed opens so we can exit with nonzero
455    status if there were any.  */
456 static int failed_opens = 0;
457
458 /* The number of spaces taken up if we print a tab character with width
459    c_ from position h_. */
460 #define TAB_WIDTH(c_, h_) ((c_) - ((h_) % (c_)))
461
462 /* The horizontal position we'll be at after printing a tab character
463    of width c_ from the position h_. */
464 #define POS_AFTER_TAB(c_, h_) ((h_) + TAB_WIDTH (c_, h_))
465
466 /* (-NNN) Number of columns of text to print. */
467 static int columns = 1;
468
469 /* (+NNN:MMM) Page numbers on which to begin and stop printing. */
470 static int first_page_number = 1;
471 static int last_page_number = 0;
472
473 /* Number of files open (not closed, not on hold). */
474 static int files_ready_to_read = 0;
475
476 /* Current page number.  Displayed in header. */
477 static int page_number;
478
479 /* Current line number.  Displayed when -n flag is specified.
480
481    When printing files in parallel (-m flag), line numbering is as follows:
482    1    foo     goo     moo
483    2    hoo     too     zoo
484
485    When printing files across (-a flag), ...
486    1    foo     2       moo     3       goo
487    4    hoo     3       too     6       zoo
488
489    Otherwise, line numbering is as follows:
490    1    foo     3       goo     5       too
491    2    moo     4       hoo     6       zoo */
492 static int line_number;
493
494 /* (-n) True means lines should be preceded by numbers. */
495 static int numbered_lines = FALSE;
496
497 /* (-n) Character which follows each line number. */
498 static char number_separator = '\t';
499
500 /* (-n) line counting starts with 1st line of input file (not with 1st
501    line of 1st page printed). */
502 static int line_count = 1;
503
504 /* (-n) True means counting of skipped lines starts with 1st line of
505    input file. False means -N option is used in addition, counting of
506    skipped lines not required. */
507 static int skip_count = TRUE;
508
509 /* (-N) Counting starts with start_line_number = NUMBER at 1st line of
510    first page printed, usually not 1st page of input file. */
511 static int start_line_num = 1;
512
513 /* (-n) Width in characters of a line number. */
514 static int chars_per_number = 5;
515
516 /* Used when widening the first column to accommodate numbers -- only
517    needed when printing files in parallel.  Includes width of both the
518    number and the number_separator. */
519 static int number_width;
520
521 /* Buffer sprintf uses to format a line number. */
522 static char *number_buff;
523
524 /* (-v) True means unprintable characters are printed as escape sequences.
525    control-g becomes \007. */
526 static int use_esc_sequence = FALSE;
527
528 /* (-c) True means unprintable characters are printed as control prefixes.
529    control-g becomes ^G. */
530 static int use_cntrl_prefix = FALSE;
531
532 /* (-d) True means output is double spaced. */
533 static int double_space = FALSE;
534
535 /* Number of files opened initially in init_files.  Should be 1
536    unless we're printing multiple files in parallel. */
537 static int total_files = 0;
538
539 /* (-r) True means don't complain if we can't open a file. */
540 static int ignore_failed_opens = FALSE;
541
542 /* (-s) True means we separate columns with a specified string.
543    -s option does not affect line truncation nor column alignment. */
544 static int use_col_separator = FALSE;
545
546 /* String used to separate columns if the -s option has been specified.
547    Default without -s but together with one of the column options
548    -a|COLUMN|-m is a `space' and with the -j option a `tab'. */
549 static char *col_sep_string;
550 static int col_sep_length = 0;
551 static char *column_separator = " ";
552 static char *line_separator = "\t";
553
554 /* Number of separator characters waiting to be printed as soon as we
555    know that we have any input remaining to be printed. */
556 static int separators_not_printed;
557
558 /* Position we need to pad to, as soon as we know that we have input
559    remaining to be printed. */
560 static int padding_not_printed;
561
562 /* True means we should pad the end of the page.  Remains false until we
563    know we have a page to print. */
564 static int pad_vertically;
565
566 /* (-h) String of characters used in place of the filename in the header. */
567 static char *custom_header;
568
569 /* String containing the date, filename or custom header, and "Page ". */
570 static char *header;
571
572 static int *clump_buff;
573
574 /* If nonzero, display usage information and exit.  */
575 static int show_help;
576
577 /* If nonzero, print the version on standard output then exit.  */
578 static int show_version;
579
580 /* True means we read the line no. lines_per_body in skip_read
581    called by skip_to_page. That variable controls the coincidence of a
582    "FF set by hand" and "full_page_printed", see above the definition of
583    structure COLUMN. */
584 static int last_line = FALSE;
585
586 /* If nonzero, print a non-variable date and time with the header
587    -h HEADER using pr test-suite */
588 static int test_suite;
589
590 static struct option const long_options[] =
591 {
592   {"help", no_argument, &show_help, 1},
593   {"version", no_argument, &show_version, 1},
594   {"test", no_argument, &test_suite, 1},
595   {0, 0, 0, 0}
596 };
597
598 /* Return the number of columns that have either an open file or
599    stored lines. */
600
601 static int
602 cols_ready_to_print (void)
603 {
604   COLUMN *q;
605   int i;
606   int n;
607
608   n = 0;
609   for (q = column_vector, i = 0; i < columns; ++q, ++i)
610     if (q->status == OPEN ||
611         q->status == FF_FOUND ||        /* With -b: To print a header only */
612         (storing_columns && q->lines_stored > 0 && q->lines_to_print > 0))
613       ++n;
614   return n;
615 }
616
617 /* Estimate first_ / last_page_number
618    using option +FIRST_PAGE:LAST_PAGE */
619
620 static void
621 first_last_page (char *pages)
622 {
623   char *str1;
624
625   if (*pages == ':')
626     {
627       error (0, 0, _("invalid range of page numbers: `%s'"), pages);
628       usage (2);
629     }
630
631   str1 = strchr (pages, ':');
632   if (str1 != NULL)
633     *str1 = '\0';
634
635   {
636     long int tmp_long;
637     if (xstrtol (pages, NULL, 10, &tmp_long, "") != LONGINT_OK
638         || tmp_long <= 0 || tmp_long > INT_MAX)
639       error (EXIT_FAILURE, 0, _("invalid starting page number: `%s'"),
640              pages);
641     first_page_number = (int) tmp_long;
642   }
643
644   if (str1 == NULL)
645     return;
646
647   {
648     long int tmp_long;
649     if (xstrtol (str1 + 1, NULL, 10, &tmp_long, "") != LONGINT_OK
650         || tmp_long <= 0 || tmp_long > INT_MAX)
651       error (EXIT_FAILURE, 0, _("invalid ending page number: `%s'"),
652              str1 + 1);
653     last_page_number = (int) tmp_long;
654   }
655
656   if (first_page_number > last_page_number)
657     error (EXIT_FAILURE, 0,
658            _("starting page number is larger than ending page number"));
659 }
660
661 /* Estimate length of col_sep_string with option -s[STRING] */
662
663 static void
664 separator_string (const char *optarg_S)
665 {
666   col_sep_length = (int) strlen (optarg_S);
667   col_sep_string = (char *) xmalloc (col_sep_length + 1);
668   strcpy (col_sep_string, optarg_S);
669 }
670
671 int
672 main (int argc, char **argv)
673 {
674   int c;
675   int accum = 0;
676   int n_files;
677   char **file_names;
678
679   program_name = argv[0];
680   setlocale (LC_ALL, "");
681   bindtextdomain (PACKAGE, LOCALEDIR);
682   textdomain (PACKAGE);
683
684   n_files = 0;
685   file_names = (argc > 1
686                 ? (char **) xmalloc ((argc - 1) * sizeof (char *))
687                 : NULL);
688
689   while (1)
690     {
691       c = getopt_long (argc, argv,
692                        "-0123456789abcde::fFh:i::jl:mn::N:o:rs::tTvw:",
693                        long_options, NULL);
694       if (c == 1)               /* Non-option argument. */
695         {
696           char *s;
697           s = optarg;
698           if (*s == '+')
699             {
700               ++s;
701               first_last_page (s);
702             }
703           else
704             {
705               file_names[n_files++] = optarg;
706             }
707         }
708       else
709         {
710           if (ISDIGIT (c))
711             {
712               accum = accum * 10 + c - '0';
713               continue;
714             }
715           else
716             {
717               if (accum > 0)
718                 {
719                   columns = accum;
720                   explicit_columns = TRUE;
721                   accum = 0;
722                 }
723             }
724         }
725
726       if (c == 1)
727         continue;
728
729       if (c == EOF)
730         break;
731
732       switch (c)
733         {
734         case 0:         /* getopt long option */
735           break;
736
737         case 'a':
738           print_across_flag = TRUE;
739           storing_columns = FALSE;
740           break;
741         case 'b':
742           balance_columns = TRUE;
743           break;
744         case 'c':
745           use_cntrl_prefix = TRUE;
746           break;
747         case 'd':
748           double_space = TRUE;
749           break;
750         case 'e':
751           if (optarg)
752             getoptarg (optarg, 'e', &input_tab_char,
753                        &chars_per_input_tab);
754           /* Could check tab width > 0. */
755           untabify_input = TRUE;
756           break;
757         case 'f':
758         case 'F':
759           use_form_feed = TRUE;
760           break;
761         case 'h':
762           custom_header = optarg;
763           standard_header = FALSE;
764           break;
765         case 'i':
766           if (optarg)
767             getoptarg (optarg, 'i', &output_tab_char,
768                        &chars_per_output_tab);
769           /* Could check tab width > 0. */
770           tabify_output = TRUE;
771           break;
772         case 'j':
773           join_lines = TRUE;
774           break;
775         case 'l':
776           {
777             long int tmp_long;
778             if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
779                 || tmp_long <= 0 || tmp_long > INT_MAX)
780               {
781                 error (EXIT_FAILURE, 0,
782                        _("`-l PAGE_LENGTH' invalid number of lines: `%s'"),
783                        optarg);
784               }
785             lines_per_page = (int) tmp_long;
786             break;
787           }
788         case 'm':
789           parallel_files = TRUE;
790           storing_columns = FALSE;
791           break;
792         case 'n':
793           numbered_lines = TRUE;
794           if (optarg)
795             getoptarg (optarg, 'n', &number_separator,
796                        &chars_per_number);
797           break;
798         case 'N':
799           skip_count = FALSE;
800           {
801             long int tmp_long;
802             if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
803                 || tmp_long > INT_MAX)
804               {
805                 error (EXIT_FAILURE, 0,
806                        _("`-N NUMBER' invalid starting line number: `%s'"),
807                        optarg);
808               }
809             start_line_num = (int) tmp_long;
810             break;
811           }
812         case 'o':
813           {
814             long int tmp_long;
815             if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
816                 || tmp_long < 0 || tmp_long > INT_MAX)
817               error (EXIT_FAILURE, 0,
818                      _("`-o MARGIN' invalid line offset: `%s'"), optarg);
819             chars_per_margin = (int) tmp_long;
820             break;
821           }
822         case 'r':
823           ignore_failed_opens = TRUE;
824           break;
825         case 's':
826           use_col_separator = TRUE;
827           if (optarg)
828             separator_string (optarg);
829           break;
830         case 't':
831           extremities = FALSE;
832           keep_FF = TRUE;
833           break;
834         case 'T':
835           extremities = FALSE;
836           keep_FF = FALSE;
837           break;
838         case 'v':
839           use_esc_sequence = TRUE;
840           break;
841         case 'w':
842           truncate_lines = TRUE;
843           {
844             long int tmp_long;
845             if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
846                 || tmp_long <= 0 || tmp_long > INT_MAX)
847               error (EXIT_FAILURE, 0,
848                  _("`-w PAGE_WIDTH' invalid column number: `%s'"), optarg);
849             chars_per_line = (int) tmp_long;
850             break;
851           }
852         default:
853           usage (2);
854           break;
855         }
856     }
857
858   if (show_version)
859     {
860       printf ("pr (%s) %s\n", GNU_PACKAGE, VERSION);
861       exit (EXIT_SUCCESS);
862     }
863
864   if (show_help)
865     usage (0);
866
867   if (parallel_files && explicit_columns)
868     error (EXIT_FAILURE, 0,
869          _("Cannot specify number of columns when printing in parallel."));
870
871   if (parallel_files && print_across_flag)
872     error (EXIT_FAILURE, 0,
873        _("Cannot specify both printing across and printing in parallel."));
874
875   for (; optind < argc; optind++)
876     {
877       file_names[n_files++] = argv[optind];
878     }
879
880   if (n_files == 0)
881     {
882       /* No file arguments specified;  read from standard input.  */
883       print_files (0, NULL);
884     }
885   else
886     {
887       if (parallel_files)
888         print_files (n_files, file_names);
889       else
890         {
891           int i;
892           for (i = 0; i < n_files; i++)
893             print_files (1, &file_names[i]);
894         }
895     }
896
897   cleanup ();
898
899   if (have_read_stdin && fclose (stdin) == EOF)
900     error (EXIT_FAILURE, errno, _("standard input"));
901   if (ferror (stdout) || fclose (stdout) == EOF)
902     error (EXIT_FAILURE, errno, _("write error"));
903   if (failed_opens > 0)
904     exit (EXIT_FAILURE);
905   exit (EXIT_SUCCESS);
906 }
907
908 /* Parse options of the form -scNNN.
909
910    Example: -nck, where 'n' is the option, c is the optional number
911    separator, and k is the optional width of the field used when printing
912    a number. */
913
914 static void
915 getoptarg (char *arg, char switch_char, char *character, int *number)
916 {
917   if (!ISDIGIT (*arg))
918     *character = *arg++;
919   if (*arg)
920     {
921       long int tmp_long;
922       if (xstrtol (arg, NULL, 10, &tmp_long, "") != LONGINT_OK
923           || tmp_long <= 0 || tmp_long > INT_MAX)
924         {
925           error (0, 0,
926                  _("`-%c' extra characters or invalid number in the argument: `%s'"),
927                  switch_char, arg);
928           usage (2);
929         }
930       *number = (int) tmp_long;
931     }
932 }
933 \f
934 /* Set parameters related to formatting. */
935
936 static void
937 init_parameters (int number_of_files)
938 {
939   int chars_used_by_number = 0;
940
941   if (use_form_feed)
942     {
943       lines_per_header = 3;
944       lines_per_footer = 0;
945     }
946
947   lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
948   if (lines_per_body <= 0)
949     {
950       extremities = FALSE;
951       keep_FF = TRUE;
952     }
953   if (extremities == FALSE)
954     lines_per_body = lines_per_page;
955
956   if (double_space)
957     lines_per_body = lines_per_body / 2;
958
959   /* If input is stdin, cannot print parallel files.  BSD dumps core
960      on this. */
961   if (number_of_files == 0)
962     parallel_files = FALSE;
963
964   if (parallel_files)
965     columns = number_of_files;
966
967   /* One file, multi columns down: -b option is set to get a consistent
968      formulation with "FF set by hand" in input files. */
969   if (storing_columns)
970     balance_columns = TRUE;
971
972   /* Tabification is assumed for multiple columns. */
973   if (columns > 1)
974     {
975       if (!use_col_separator)
976         {
977           /* Use default separator */
978           if (join_lines)
979             col_sep_string = line_separator;
980           else
981             col_sep_string = column_separator;
982           col_sep_length = 1;
983           use_col_separator = TRUE;
984         }
985
986       truncate_lines = TRUE;
987       untabify_input = TRUE;
988       tabify_output = TRUE;
989     }
990   else
991     storing_columns = FALSE;
992
993   /* -j dominates -w in any case */
994   if (join_lines)
995     truncate_lines = FALSE;
996
997   if (numbered_lines)
998     {
999       line_count = start_line_num;
1000       if (number_separator == input_tab_char)
1001         {
1002           number_width = chars_per_number +
1003             TAB_WIDTH (chars_per_input_tab,
1004                        (chars_per_margin + chars_per_number));
1005         }
1006       else
1007         number_width = chars_per_number + 1;
1008       /* The number is part of the column width unless we are
1009          printing files in parallel. */
1010       if (parallel_files)
1011         chars_used_by_number = number_width;
1012     }
1013
1014   chars_per_column = (chars_per_line - chars_used_by_number -
1015                       (columns - 1) * col_sep_length) / columns;
1016
1017   if (chars_per_column < 1)
1018     error (EXIT_FAILURE, 0, _("page width too narrow"));
1019
1020   if (numbered_lines)
1021     {
1022       if (number_buff != NULL)
1023         free (number_buff);
1024       number_buff = (char *) xmalloc (2 * chars_per_number);
1025     }
1026
1027   /* Pick the maximum between the tab width and the width of an
1028      escape sequence. */
1029   if (clump_buff != NULL)
1030     free (clump_buff);
1031   clump_buff = (int *) xmalloc ((chars_per_input_tab > 4
1032                                  ? chars_per_input_tab : 4) * sizeof (int));
1033 }
1034 \f
1035 /* Open the necessary files,
1036    maintaining a COLUMN structure for each column.
1037
1038    With multiple files, each column p has a different p->fp.
1039    With single files, each column p has the same p->fp.
1040    Return 1 if (number_of_files > 0) and no files can be opened,
1041    0 otherwise.
1042
1043    With each column/file p, p->full_page_printed is initialized,
1044    see also open_file.  */
1045
1046 static int
1047 init_fps (int number_of_files, char **av)
1048 {
1049   int i, files_left;
1050   COLUMN *p;
1051   FILE *firstfp;
1052   char *firstname;
1053
1054   total_files = 0;
1055
1056   if (column_vector != NULLCOL)
1057     free ((char *) column_vector);
1058   column_vector = (COLUMN *) xmalloc (columns * sizeof (COLUMN));
1059
1060   if (parallel_files)
1061     {
1062       files_left = number_of_files;
1063       for (p = column_vector; files_left--; ++p, ++av)
1064         {
1065           if (open_file (*av, p) == 0)
1066             {
1067               --p;
1068               --columns;
1069             }
1070         }
1071       if (columns == 0)
1072         return 1;
1073       init_header ("", -1);
1074     }
1075   else
1076     {
1077       p = column_vector;
1078       if (number_of_files > 0)
1079         {
1080           if (open_file (*av, p) == 0)
1081             return 1;
1082           init_header (*av, fileno (p->fp));
1083           p->lines_stored = 0;
1084         }
1085       else
1086         {
1087           p->name = _("standard input");
1088           p->fp = stdin;
1089           have_read_stdin = TRUE;
1090           p->status = OPEN;
1091           p->full_page_printed = FALSE;
1092           ++total_files;
1093           init_header ("", -1);
1094           p->lines_stored = 0;
1095         }
1096
1097       firstname = p->name;
1098       firstfp = p->fp;
1099       for (i = columns - 1, ++p; i; --i, ++p)
1100         {
1101           p->name = firstname;
1102           p->fp = firstfp;
1103           p->status = OPEN;
1104           p->full_page_printed = FALSE;
1105           p->lines_stored = 0;
1106         }
1107     }
1108   files_ready_to_read = total_files;
1109   return 0;
1110 }
1111 \f
1112 /* Determine print_func and char_func, the functions
1113    used by each column for printing and/or storing.
1114
1115    Determine the horizontal position desired when we begin
1116    printing a column (p->start_position). */
1117
1118 static void
1119 init_funcs (void)
1120 {
1121   int i, h, h_next;
1122   COLUMN *p;
1123
1124   h = chars_per_margin;
1125
1126   if (!truncate_lines)
1127     h_next = ANYWHERE;
1128   else
1129     {
1130       /* When numbering lines of parallel files, we enlarge the
1131          first column to accomodate the number.  Looks better than
1132          the Sys V approach. */
1133       if (parallel_files && numbered_lines)
1134         h_next = h + chars_per_column + number_width;
1135       else
1136         h_next = h + chars_per_column;
1137     }
1138
1139   /* Enlarge p->start_position of first column to use the same form of
1140      padding_not_printed with all columns. */
1141   h = h + col_sep_length;
1142
1143   /* This loop takes care of all but the rightmost column. */
1144
1145   for (p = column_vector, i = 1; i < columns; ++p, ++i)
1146     {
1147       if (storing_columns)      /* One file, multi columns down. */
1148         {
1149           p->char_func = store_char;
1150           p->print_func = print_stored;
1151         }
1152       else
1153         /* One file, multi columns across; or parallel files.  */
1154         {
1155           p->char_func = print_char;
1156           p->print_func = read_line;
1157         }
1158
1159       /* Number only the first column when printing files in
1160          parallel. */
1161       p->numbered = numbered_lines && (!parallel_files || i == 1);
1162       p->start_position = h;
1163
1164       /* If we don't truncate lines, all start_positions are
1165          ANYWHERE, except the first column's start_position when
1166          using a margin. */
1167
1168       if (!truncate_lines)
1169         {
1170           h = ANYWHERE;
1171           h_next = ANYWHERE;
1172         }
1173       else
1174         {
1175           h = h_next + col_sep_length;
1176           h_next = h + chars_per_column;
1177         }
1178     }
1179
1180   /* The rightmost column.
1181
1182      Doesn't need to be stored unless we intend to balance
1183      columns on the last page. */
1184   if (storing_columns && balance_columns)
1185     {
1186       p->char_func = store_char;
1187       p->print_func = print_stored;
1188     }
1189   else
1190     {
1191       p->char_func = print_char;
1192       p->print_func = read_line;
1193     }
1194
1195   p->numbered = numbered_lines && (!parallel_files || i == 1);
1196   p->start_position = h;
1197 }
1198 \f
1199 /* Open a file.  Return nonzero if successful, zero if failed.
1200
1201    With each file p, p->full_page_printed is initialized,
1202    see also init_fps. */
1203
1204 static int
1205 open_file (char *name, COLUMN *p)
1206 {
1207   if (!strcmp (name, "-"))
1208     {
1209       p->name = _("standard input");
1210       p->fp = stdin;
1211       have_read_stdin = 1;
1212     }
1213   else
1214     {
1215       p->name = name;
1216       p->fp = fopen (name, "r");
1217     }
1218   if (p->fp == NULL)
1219     {
1220       ++failed_opens;
1221       if (!ignore_failed_opens)
1222         error (0, errno, "%s", name);
1223       return 0;
1224     }
1225   p->status = OPEN;
1226   p->full_page_printed = FALSE;
1227   ++total_files;
1228   return 1;
1229 }
1230
1231 /* Close the file in P.
1232
1233    If we aren't dealing with multiple files in parallel, we change
1234    the status of all columns in the column list to reflect the close. */
1235
1236 static void
1237 close_file (COLUMN *p)
1238 {
1239   COLUMN *q;
1240   int i;
1241
1242   if (p->status == CLOSED)
1243     return;
1244   if (ferror (p->fp))
1245     error (EXIT_FAILURE, errno, "%s", p->name);
1246   if (p->fp != stdin && fclose (p->fp) == EOF)
1247     error (EXIT_FAILURE, errno, "%s", p->name);
1248
1249   if (!parallel_files)
1250     {
1251       for (q = column_vector, i = columns; i; ++q, --i)
1252         {
1253           q->status = CLOSED;
1254           if (q->lines_stored == 0)
1255             {
1256               q->lines_to_print = 0;
1257             }
1258         }
1259     }
1260   else
1261     {
1262       p->status = CLOSED;
1263       p->lines_to_print = 0;
1264     }
1265
1266   --files_ready_to_read;
1267 }
1268
1269 /* Put a file on hold until we start a new page,
1270    since we've hit a form feed.
1271
1272    If we aren't dealing with parallel files, we must change the
1273    status of all columns in the column list. */
1274
1275 static void
1276 hold_file (COLUMN *p)
1277 {
1278   COLUMN *q;
1279   int i;
1280
1281   if (!parallel_files)
1282     for (q = column_vector, i = columns; i; ++q, --i)
1283       {
1284         if (storing_columns)
1285           q->status = FF_FOUND;
1286         else
1287           q->status = ON_HOLD;
1288       }
1289   else
1290     p->status = ON_HOLD;
1291
1292   p->lines_to_print = 0;
1293   --files_ready_to_read;
1294 }
1295
1296 /* Undo hold_file -- go through the column list and change any
1297    ON_HOLD columns to OPEN.  Used at the end of each page. */
1298
1299 static void
1300 reset_status (void)
1301 {
1302   int i = columns;
1303   COLUMN *p;
1304
1305   for (p = column_vector; i; --i, ++p)
1306     if (p->status == ON_HOLD)
1307       {
1308         p->status = OPEN;
1309         files_ready_to_read++;
1310       }
1311
1312   if (storing_columns)
1313     files_ready_to_read = 1;
1314 }
1315 \f
1316 /* Print a single file, or multiple files in parallel.
1317
1318    Set up the list of columns, opening the necessary files.
1319    Allocate space for storing columns, if necessary.
1320    Skip to first_page_number, if user has asked to skip leading pages.
1321    Determine which functions are appropriate to store/print lines
1322    in each column.
1323    Print the file(s). */
1324
1325 static void
1326 print_files (int number_of_files, char **av)
1327 {
1328   init_parameters (number_of_files);
1329   if (init_fps (number_of_files, av))
1330     return;
1331   if (storing_columns)
1332     init_store_cols ();
1333
1334   if (first_page_number > 1)
1335     {
1336       if (!skip_to_page (first_page_number))
1337         return;
1338       else
1339         page_number = first_page_number;
1340     }
1341   else
1342     page_number = 1;
1343
1344   init_funcs ();
1345
1346   line_number = line_count;
1347   while (print_page ())
1348     ;
1349 }
1350 \f
1351 /* Estimate the number of characters taken up by a short format date and
1352    time:  "yy-mm-dd HH:MM"  and:  "Page NNNN". */
1353 #define CHARS_FOR_DATE_AND_PAGE 23
1354
1355 /* Initialize header information.
1356    If DESC is non-negative, it is a file descriptor open to
1357    FILENAME for reading.
1358
1359    Allocate space for a header string,
1360    Determine the time, insert file name or user-specified string.
1361    Make use of a centered header with left-hand-side truncation marked by
1362    a '*` in front, if necessary. */
1363
1364 static void
1365 init_header (char *filename, int desc)
1366 {
1367   int chars_per_middle, chars_free, lhs_blanks, rhs_blanks;
1368   char *f = filename;
1369   char *no_middle = "";
1370   char *header_text;
1371   struct tm *tmptr;
1372   struct stat st;
1373   char *datim = "- Date/Time --";
1374
1375   if (filename == NULL)
1376     f = "";
1377
1378   if (header != NULL)
1379     free (header);
1380   header = (char *) xmalloc (chars_per_line + 1);
1381
1382   if (!standard_header && *custom_header == '\0')
1383     sprintf (header, "%s", " ");        /* blank line header */
1384   else
1385     {
1386 #define T_BUF_FMT "%Y-%m-%d %H:%M"      /* date/time short format */
1387 #define T_BUF_SIZE 17  /* FIXME: using a literal here is fragile.  */
1388       char t_buf[T_BUF_SIZE];
1389
1390       /* If parallel files or standard input, use current time. */
1391       if (desc < 0 || !strcmp (filename, "-") || fstat (desc, &st))
1392         st.st_mtime = time (NULL);
1393
1394       tmptr = localtime (&st.st_mtime);
1395       strftime (t_buf, T_BUF_SIZE, T_BUF_FMT, tmptr);
1396
1397       chars_per_middle = chars_per_line - CHARS_FOR_DATE_AND_PAGE;
1398       if (chars_per_middle < 3)
1399         {
1400           header_text = no_middle;      /* Nothing free for a heading */
1401           lhs_blanks = 1;
1402           rhs_blanks = 1;
1403         }
1404       else
1405         {
1406           header_text = standard_header ? f : custom_header;
1407           chars_free = chars_per_middle - (int) strlen (header_text);
1408           if (chars_free > 1)
1409             {
1410               lhs_blanks = chars_free / 2;      /* text not truncated */
1411               rhs_blanks = chars_free - lhs_blanks;
1412             }
1413           else
1414             {                   /* lhs truncation */
1415               header_text = header_text - chars_free + 2;
1416               *header_text = '*';
1417               lhs_blanks = 1;
1418               rhs_blanks = 1;
1419             }
1420         }
1421
1422       sprintf (header, _("%s%*s%s%*sPage"), (test_suite ? datim : t_buf),
1423                lhs_blanks, " ", header_text, rhs_blanks, " ");
1424     }
1425 }
1426 \f
1427 /* Set things up for printing a page
1428
1429    Scan through the columns ...
1430    Determine which are ready to print
1431    (i.e., which have lines stored or open files)
1432    Set p->lines_to_print appropriately
1433    (to p->lines_stored if we're storing, or lines_per_body
1434    if we're reading straight from the file)
1435    Keep track of this total so we know when to stop printing */
1436
1437 static void
1438 init_page (void)
1439 {
1440   int j;
1441   COLUMN *p;
1442
1443   if (storing_columns)
1444     {
1445       store_columns ();
1446       for (j = columns - 1, p = column_vector; j; --j, ++p)
1447         {
1448           p->lines_to_print = p->lines_stored;
1449         }
1450
1451       /* Last column. */
1452       if (balance_columns)
1453         {
1454           p->lines_to_print = p->lines_stored;
1455         }
1456       /* Since we're not balancing columns, we don't need to store
1457          the rightmost column.   Read it straight from the file. */
1458       else
1459         {
1460           if (p->status == OPEN)
1461             {
1462               p->lines_to_print = lines_per_body;
1463             }
1464           else
1465             p->lines_to_print = 0;
1466         }
1467     }
1468   else
1469     for (j = columns, p = column_vector; j; --j, ++p)
1470       if (p->status == OPEN)
1471         {
1472           p->lines_to_print = lines_per_body;
1473         }
1474       else
1475         p->lines_to_print = 0;
1476 }
1477
1478 /* Align empty columns and print separators.
1479    Empty columns will be formed by files with status ON_HOLD or CLOSED
1480    when printing multiple files in parallel. */
1481
1482 static void
1483 align_column (COLUMN *p)
1484 {
1485   padding_not_printed = p->start_position;
1486   if (padding_not_printed - col_sep_length > 0)
1487     {
1488       pad_across_to (padding_not_printed - col_sep_length);
1489       padding_not_printed = ANYWHERE;
1490     }
1491
1492   if (use_col_separator)
1493     print_sep_string ();
1494
1495   if (p->numbered)
1496     add_line_number (p);
1497 }
1498
1499 /* Print one page.
1500
1501    As long as there are lines left on the page and columns ready to print,
1502    Scan across the column list
1503    if the column has stored lines or the file is open
1504    pad to the appropriate spot
1505    print the column
1506    pad the remainder of the page with \n or \f as requested
1507    reset the status of all files -- any files which where on hold because
1508    of formfeeds are now put back into the lineup. */
1509
1510 static int
1511 print_page (void)
1512 {
1513   int j;
1514   int lines_left_on_page;
1515   COLUMN *p;
1516
1517   /* Used as an accumulator (with | operator) of successive values of
1518      pad_vertically.  The trick is to set pad_vertically
1519      to zero before each run through the inner loop, then after that
1520      loop, it tells us whether a line was actually printed (whether a
1521      newline needs to be output -- or two for double spacing).  But those
1522      values have to be accumulated (in pv) so we can invoke pad_down
1523      properly after the outer loop completes. */
1524   int pv;
1525
1526   init_page ();
1527
1528   if (cols_ready_to_print () == 0)
1529     return FALSE;
1530
1531   if (extremities)
1532     print_a_header = TRUE;
1533
1534   /* Don't pad unless we know a page was printed. */
1535   pad_vertically = FALSE;
1536   pv = FALSE;
1537
1538   lines_left_on_page = lines_per_body;
1539   if (double_space)
1540     lines_left_on_page *= 2;
1541
1542   while (lines_left_on_page > 0 && cols_ready_to_print () > 0)
1543     {
1544       output_position = 0;
1545       spaces_not_printed = 0;
1546       separators_not_printed = 0;
1547       pad_vertically = FALSE;
1548       align_empty_cols = FALSE;
1549       empty_line = TRUE;
1550
1551       for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1552         {
1553           input_position = 0;
1554           if (p->lines_to_print > 0 || p->status == FF_FOUND)
1555             {
1556               FF_only = FALSE;
1557               padding_not_printed = p->start_position;
1558               if (!(p->print_func) (p))
1559                 read_rest_of_line (p);
1560               pv |= pad_vertically;
1561
1562               --p->lines_to_print;
1563               if (p->lines_to_print <= 0)
1564                 {
1565                   if (cols_ready_to_print () <= 0)
1566                     break;
1567                 }
1568
1569               /* File p changed its status to ON_HOLD or CLOSED */
1570               if (parallel_files && p->status != OPEN)
1571                 {
1572                   if (empty_line)
1573                     align_empty_cols = TRUE;
1574                   else if (p->status == CLOSED ||
1575                            (p->status == ON_HOLD && FF_only))
1576                     align_column (p);
1577                 }
1578             }
1579           else if (parallel_files)
1580             {
1581               /* File status ON_HOLD or CLOSED */
1582               if (empty_line)
1583                 align_empty_cols = TRUE;
1584               else
1585                 align_column (p);
1586             }
1587
1588           /* We need it also with an empty column */
1589           if (use_col_separator)
1590             ++separators_not_printed;
1591         }
1592
1593       if (pad_vertically)
1594         {
1595           putchar ('\n');
1596           --lines_left_on_page;
1597         }
1598
1599       if (double_space && pv && extremities)
1600         {
1601           putchar ('\n');
1602           --lines_left_on_page;
1603         }
1604     }
1605
1606   if (lines_left_on_page == 0)
1607     for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1608       if (p->status == OPEN)
1609         p->full_page_printed = TRUE;
1610
1611   pad_vertically = pv;
1612
1613   if (pad_vertically && extremities)
1614     pad_down (lines_left_on_page + lines_per_footer);
1615   else if (keep_FF && print_a_FF)
1616     {
1617       putchar ('\f');
1618       print_a_FF = FALSE;
1619     }
1620
1621   if (last_page_number && page_number > last_page_number)
1622     return FALSE;               /* Stop printing with LAST_PAGE */
1623
1624   reset_status ();              /* Change ON_HOLD to OPEN. */
1625
1626   return TRUE;                  /* More pages to go. */
1627 }
1628 \f
1629 /* Allocate space for storing columns.
1630
1631    This is necessary when printing multiple columns from a single file.
1632    Lines are stored consecutively in buff, separated by '\0'.
1633
1634    The following doesn't apply any longer - any tuning possible?
1635    (We can't use a fixed offset since with the '-s' flag lines aren't
1636    truncated.)
1637
1638    We maintain a list (line_vector) of pointers to the beginnings
1639    of lines in buff.  We allocate one more than the number of lines
1640    because the last entry tells us the index of the last character,
1641    which we need to know in order to print the last line in buff. */
1642
1643 static void
1644 init_store_cols (void)
1645 {
1646   int total_lines = lines_per_body * columns;
1647   int chars_if_truncate = total_lines * (chars_per_column + 1);
1648
1649   if (line_vector != NULL)
1650     free ((int *) line_vector);
1651   /* FIXME: here's where it was allocated.  */
1652   line_vector = (int *) xmalloc ((total_lines + 1) * sizeof (int *));
1653
1654   if (end_vector != NULL)
1655     free ((int *) end_vector);
1656   end_vector = (int *) xmalloc (total_lines * sizeof (int *));
1657
1658   if (buff != NULL)
1659     free (buff);
1660   buff_allocated = (use_col_separator
1661                     ? 2 * chars_if_truncate
1662                     : chars_if_truncate);       /* Tune this. */
1663   buff = (char *) xmalloc (buff_allocated);
1664 }
1665
1666 /* Store all but the rightmost column.
1667    (Used when printing a single file in multiple downward columns)
1668
1669    For each column
1670    set p->current_line to be the index in line_vector of the
1671    first line in the column
1672    For each line in the column
1673    store the line in buff
1674    add to line_vector the index of the line's first char
1675    buff_start is the index in buff of the first character in the
1676    current line. */
1677
1678 static void
1679 store_columns (void)
1680 {
1681   int i, j;
1682   int line = 0;
1683   int buff_start;
1684   int last_col;                 /* The rightmost column which will be saved in buff */
1685   COLUMN *p;
1686
1687   buff_current = 0;
1688   buff_start = 0;
1689
1690   if (balance_columns)
1691     last_col = columns;
1692   else
1693     last_col = columns - 1;
1694
1695   for (i = 1, p = column_vector; i <= last_col; ++i, ++p)
1696     p->lines_stored = 0;
1697
1698   for (i = 1, p = column_vector; i <= last_col && files_ready_to_read;
1699        ++i, ++p)
1700     {
1701       p->current_line = line;
1702       for (j = lines_per_body; j && files_ready_to_read; --j)
1703
1704         if (p->status == OPEN)  /* Redundant.  Clean up. */
1705           {
1706             input_position = 0;
1707
1708             if (!read_line (p))
1709               read_rest_of_line (p);
1710
1711             if (p->status == OPEN
1712                 || buff_start != buff_current)
1713               {
1714                 ++p->lines_stored;
1715                 line_vector[line] = buff_start;
1716                 end_vector[line++] = input_position;
1717                 buff_start = buff_current;
1718               }
1719           }
1720     }
1721
1722   /* Keep track of the location of the last char in buff. */
1723   line_vector[line] = buff_start;
1724
1725   if (balance_columns && p->lines_stored != lines_per_body)
1726     balance (line);
1727 }
1728
1729 static void
1730 balance (int total_stored)
1731 {
1732   COLUMN *p;
1733   int i, lines;
1734   int first_line = 0;
1735
1736   for (i = 1, p = column_vector; i <= columns; ++i, ++p)
1737     {
1738       lines = total_stored / columns;
1739       if (i <= total_stored % columns)
1740         ++lines;
1741
1742       p->lines_stored = lines;
1743       p->current_line = first_line;
1744
1745       first_line += lines;
1746     }
1747 }
1748
1749 /* Store a character in the buffer. */
1750
1751 static void
1752 store_char (int c)
1753 {
1754   if (buff_current >= buff_allocated)
1755     {
1756       /* May be too generous. */
1757       buff_allocated = 2 * buff_allocated;
1758       buff = (char *) xrealloc (buff, buff_allocated * sizeof (char));
1759     }
1760   buff[buff_current++] = (char) c;
1761 }
1762
1763 static void
1764 add_line_number (COLUMN *p)
1765 {
1766   int i;
1767   char *s;
1768
1769   sprintf (number_buff, "%*d", chars_per_number, line_number++);
1770   s = number_buff;
1771   for (i = chars_per_number; i > 0; i--)
1772     (p->char_func) ((int) *s++);
1773
1774   if (number_separator == input_tab_char)
1775     {
1776       i = number_width - chars_per_number;
1777       while (i-- > 0)
1778         (p->char_func) ((int) ' ');
1779     }
1780   else
1781     (p->char_func) ((int) number_separator);
1782
1783   if (truncate_lines && !parallel_files)
1784     input_position += number_width;
1785 }
1786 \f
1787 /* Print (or store) padding until the current horizontal position
1788    is position. */
1789
1790 static void
1791 pad_across_to (int position)
1792 {
1793   register int h = output_position;
1794
1795   if (tabify_output)
1796     spaces_not_printed = position - output_position;
1797   else
1798     {
1799       while (++h <= position)
1800         putchar (' ');
1801       output_position = position;
1802     }
1803 }
1804
1805 /* Pad to the bottom of the page.
1806
1807    If the user has requested a formfeed, use one.
1808    Otherwise, use newlines. */
1809
1810 static void
1811 pad_down (int lines)
1812 {
1813   register int i;
1814
1815   if (use_form_feed)
1816     putchar ('\f');
1817   else
1818     for (i = lines; i; --i)
1819       putchar ('\n');
1820 }
1821
1822 /* Read the rest of the line.
1823
1824    Read from the current column's file until an end of line is
1825    hit.  Used when we've truncated a line and we no longer need
1826    to print or store its characters. */
1827
1828 static void
1829 read_rest_of_line (COLUMN *p)
1830 {
1831   register int c;
1832   FILE *f = p->fp;
1833
1834   while ((c = getc (f)) != '\n')
1835     {
1836       if (c == '\f')
1837         {
1838           if ((c = getc (f)) != '\n')
1839             ungetc (c, f);
1840           if (keep_FF)
1841             print_a_FF = TRUE;
1842           hold_file (p);
1843           break;
1844         }
1845       else if (c == EOF)
1846         {
1847           close_file (p);
1848           break;
1849         }
1850     }
1851 }
1852
1853 /* Read a line with skip_to_page.
1854
1855    Read from the current column's file until an end of line is
1856    hit.  Used when we read full lines to skip pages.
1857    With skip_to_page we have to check for FF-coincidence which is done
1858    in function read_line otherwise.
1859    Count lines of skipped pages to find the line number of 1st page
1860    printed relative to 1st line of input file (start_line_num). */
1861
1862 static void
1863 skip_read (COLUMN *p, int column_number)
1864 {
1865   register int c;
1866   FILE *f = p->fp;
1867   int i, single_ff = FALSE;
1868   COLUMN *q;
1869
1870   /* Read 1st character in a line or any character succeeding a FF */
1871   if ((c = getc (f)) == '\f' && p->full_page_printed)
1872     /* A FF-coincidence with a previous full_page_printed.
1873        To avoid an additional empty page, eliminate the FF */
1874     if ((c = getc (f)) == '\n')
1875       c = getc (f);
1876
1877   p->full_page_printed = FALSE;
1878
1879   /* 1st character a FF means a single FF without any printable
1880      characters. Don't count it as a line with -n option. */
1881   if (c == '\f')
1882     single_ff = TRUE;
1883
1884   /* Preparing for a FF-coincidence: Maybe we finish that page
1885      without a FF found */
1886   if (last_line)
1887     p->full_page_printed = TRUE;
1888
1889   while (c != '\n')
1890     {
1891       if (c == '\f')
1892         {
1893           /* No FF-coincidence possible,
1894              no catching up of a FF-coincidence with next page */
1895           if (last_line)
1896             {
1897               if (!parallel_files)
1898                 for (q = column_vector, i = columns; i; ++q, --i)
1899                   q->full_page_printed = FALSE;
1900               else
1901                 p->full_page_printed = FALSE;
1902             }
1903
1904           if ((c = getc (f)) != '\n')
1905             ungetc (c, f);
1906           hold_file (p);
1907           break;
1908         }
1909       else if (c == EOF)
1910         {
1911           close_file (p);
1912           break;
1913         }
1914       c = getc (f);
1915     }
1916
1917   if (skip_count)
1918     if ((!parallel_files || column_number == 1) && !single_ff)
1919       ++line_count;
1920 }
1921 \f
1922 /* If we're tabifying output,
1923
1924    When print_char encounters white space it keeps track
1925    of our desired horizontal position and delays printing
1926    until this function is called. */
1927
1928 static void
1929 print_white_space (void)
1930 {
1931   register int h_new;
1932   register int h_old = output_position;
1933   register int goal = h_old + spaces_not_printed;
1934
1935   while (goal - h_old > 1
1936          && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal)
1937     {
1938       putchar (output_tab_char);
1939       h_old = h_new;
1940     }
1941   while (++h_old <= goal)
1942     putchar (' ');
1943
1944   output_position = goal;
1945   spaces_not_printed = 0;
1946 }
1947
1948 /* Print column separators.
1949
1950    We keep a count until we know that we'll be printing a line,
1951    then print_sep_string() is called. */
1952
1953 static void
1954 print_sep_string ()
1955 {
1956   char *s;
1957   int l = col_sep_length;
1958
1959   s = col_sep_string;
1960
1961   if (spaces_not_printed > 0)
1962     print_white_space ();
1963
1964   for (; separators_not_printed > 0; --separators_not_printed)
1965     {
1966       while (l-- > 0)
1967         putchar (*s++);
1968       output_position += col_sep_length;
1969     }
1970 }
1971
1972 /* Print (or store, depending on p->char_func) a clump of N
1973    characters. */
1974
1975 static void
1976 print_clump (COLUMN *p, int n, int *clump)
1977 {
1978   while (n--)
1979     (p->char_func) (*clump++);
1980 }
1981
1982 /* Print a character.
1983
1984    Update the following comment: process-char hasn't been used any
1985    longer.
1986    If we're tabifying, all tabs have been converted to spaces by
1987    process_char().  Keep a count of consecutive spaces, and when
1988    a nonspace is encountered, call print_white_space() to print the
1989    required number of tabs and spaces. */
1990
1991 static void
1992 print_char (int c)
1993 {
1994   if (tabify_output)
1995     {
1996       if (c == ' ')
1997         {
1998           ++spaces_not_printed;
1999           return;
2000         }
2001       else if (spaces_not_printed > 0)
2002         print_white_space ();
2003
2004       /* Nonprintables are assumed to have width 0, except '\b'. */
2005       if (!ISPRINT (c))
2006         {
2007           if (c == '\b')
2008             --output_position;
2009         }
2010       else
2011         ++output_position;
2012     }
2013   putchar (c);
2014 }
2015
2016 /* Skip to page PAGE before printing. */
2017
2018 static int
2019 skip_to_page (int page)
2020 {
2021   int n, i, j;
2022   COLUMN *p;
2023
2024   for (n = 1; n < page; ++n)
2025     {
2026       for (i = 1; i < lines_per_body; ++i)
2027         {
2028           for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2029             if (p->status == OPEN)
2030               skip_read (p, j);
2031         }
2032       last_line = TRUE;
2033       for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2034         if (p->status == OPEN)
2035           skip_read (p, j);
2036
2037       if (storing_columns)      /* change FF_FOUND to ON_HOLD */
2038         for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2039           p->status = ON_HOLD;
2040
2041       reset_status ();
2042       last_line = FALSE;
2043     }
2044   return files_ready_to_read > 0;
2045 }
2046
2047 /* Print a header.
2048
2049    Formfeeds are assumed to use up two lines at the beginning of
2050    the page. */
2051
2052 static void
2053 print_header (void)
2054 {
2055   if (!use_form_feed)
2056     fprintf (stdout, "\n\n");
2057
2058   output_position = 0;
2059   pad_across_to (chars_per_margin);
2060   print_white_space ();
2061
2062   if (!standard_header && *custom_header == '\0')
2063     fprintf (stdout, "%s\n\n\n", header);
2064   else
2065     fprintf (stdout, "%s%5d\n\n\n", header, page_number++);
2066
2067   print_a_header = FALSE;
2068   output_position = 0;
2069 }
2070
2071 /* Print (or store, if p->char_func is store_char()) a line.
2072
2073    Read a character to determine whether we have a line or not.
2074    (We may hit EOF, \n, or \f)
2075
2076    Once we know we have a line,
2077    set pad_vertically = TRUE, meaning it's safe
2078    to pad down at the end of the page, since we do have a page.
2079    print a header if needed.
2080    pad across to padding_not_printed if needed.
2081    print any separators which need to be printed.
2082    print a line number if it needs to be printed.
2083
2084    Print the clump which corresponds to the first character.
2085
2086    Enter a loop and keep printing until an end of line condition
2087    exists, or until we exceed chars_per_column.
2088
2089    Return FALSE if we exceed chars_per_column before reading
2090    an end of line character, TRUE otherwise. */
2091
2092 static int
2093 read_line (COLUMN *p)
2094 {
2095   register int c, chars;
2096   int last_input_position;
2097   int j, k;
2098   COLUMN *q;
2099
2100 /* Suppress `used before initialized' warning. */
2101 #ifdef lint
2102   chars = 0;
2103 #endif
2104
2105   /* read 1st character in each line or any character succeeding a FF: */
2106   c = getc (p->fp);
2107
2108   last_input_position = input_position;
2109
2110   if (c == '\f' && p->full_page_printed)
2111     if ((c = getc (p->fp)) == '\n')
2112       c = getc (p->fp);
2113   p->full_page_printed = FALSE;
2114
2115   switch (c)
2116     {
2117     case '\f':
2118       if ((c = getc (p->fp)) != '\n')
2119         ungetc (c, p->fp);
2120       FF_only = TRUE;
2121       if (print_a_header && !storing_columns)
2122         {
2123           pad_vertically = TRUE;
2124           print_header ();
2125         }
2126       else if (keep_FF)
2127         print_a_FF = TRUE;
2128       hold_file (p);
2129       return TRUE;
2130     case EOF:
2131       close_file (p);
2132       return TRUE;
2133     case '\n':
2134       break;
2135     default:
2136       chars = char_to_clump (c);
2137     }
2138
2139   if (truncate_lines && input_position > chars_per_column)
2140     {
2141       input_position = last_input_position;
2142       return FALSE;
2143     }
2144
2145   if (p->char_func != store_char)
2146     {
2147       pad_vertically = TRUE;
2148
2149       if (print_a_header && !storing_columns)
2150         print_header ();
2151
2152       if (parallel_files && align_empty_cols)
2153         {
2154           /* We have to align empty columns at the beginning of a line. */
2155           k = separators_not_printed;
2156           separators_not_printed = 0;
2157           for (j = 1, q = column_vector; j <= k; ++j, ++q)
2158             {
2159               align_column (q);
2160               separators_not_printed += 1;
2161             }
2162           padding_not_printed = p->start_position;
2163           if (truncate_lines)
2164             spaces_not_printed = chars_per_column;
2165           else
2166             spaces_not_printed = 0;
2167           align_empty_cols = FALSE;
2168         }
2169
2170       if (padding_not_printed - col_sep_length > 0)
2171         {
2172           pad_across_to (padding_not_printed - col_sep_length);
2173           padding_not_printed = ANYWHERE;
2174         }
2175
2176       if (use_col_separator)
2177         print_sep_string ();
2178     }
2179
2180   if (p->numbered)
2181     add_line_number (p);
2182
2183   empty_line = FALSE;
2184   if (c == '\n')
2185     return TRUE;
2186
2187   print_clump (p, chars, clump_buff);
2188
2189   for (;;)
2190     {
2191       c = getc (p->fp);
2192
2193       switch (c)
2194         {
2195         case '\n':
2196           return TRUE;
2197         case '\f':
2198           if ((c = getc (p->fp)) != '\n')
2199             ungetc (c, p->fp);
2200           if (keep_FF)
2201             print_a_FF = TRUE;
2202           hold_file (p);
2203           return TRUE;
2204         case EOF:
2205           close_file (p);
2206           return TRUE;
2207         }
2208
2209       last_input_position = input_position;
2210       chars = char_to_clump (c);
2211       if (truncate_lines && input_position > chars_per_column)
2212         {
2213           input_position = last_input_position;
2214           return FALSE;
2215         }
2216
2217       print_clump (p, chars, clump_buff);
2218     }
2219 }
2220
2221 /* Print a line from buff.
2222
2223    If this function has been called, we know we have "something to
2224    print". But it remains to be seen whether we have a real text page
2225    or an empty page (a single form feed) with/without a header only.
2226    Therefore first we set pad_vertically to TRUE and print a header
2227    if necessary.
2228    If FF_FOUND and we are using -t|-T option we omit any newline by
2229    setting pad_vertically to FALSE (see print_page).
2230    Otherwise we pad across if necessary, print separators if necessary
2231    and text of COLUMN *p.
2232
2233    Return TRUE, meaning there is no need to call read_rest_of_line. */
2234
2235 static int
2236 print_stored (COLUMN *p)
2237 {
2238   COLUMN *q;
2239   int i;
2240
2241   int line = p->current_line++;
2242   register char *first = &buff[line_vector[line]];
2243   /* FIXME
2244      UMR: Uninitialized memory read:
2245      * This is occurring while in:
2246      print_stored   [pr.c:2239]
2247      * Reading 4 bytes from 0x5148c in the heap.
2248      * Address 0x5148c is 4 bytes into a malloc'd block at 0x51488 of 676 bytes
2249      * This block was allocated from:
2250      malloc         [rtlib.o]
2251      xmalloc        [xmalloc.c:94]
2252      init_store_cols [pr.c:1648]
2253      */
2254   register char *last = &buff[line_vector[line + 1]];
2255
2256   pad_vertically = TRUE;
2257
2258   if (print_a_header)
2259     print_header ();
2260
2261   if (p->status == FF_FOUND)
2262     {
2263       for (i = 1, q = column_vector; i <= columns; ++i, ++q)
2264         q->status = ON_HOLD;
2265       if (column_vector->lines_to_print <= 0)
2266         {
2267           if (!extremities)
2268             pad_vertically = FALSE;
2269           return TRUE;          /* print a header only */
2270         }
2271     }
2272
2273   if (padding_not_printed - col_sep_length > 0)
2274     {
2275       pad_across_to (padding_not_printed - col_sep_length);
2276       padding_not_printed = ANYWHERE;
2277     }
2278
2279   if (use_col_separator)
2280     print_sep_string ();
2281
2282   while (first != last)
2283     print_char (*first++);
2284
2285   if (spaces_not_printed == 0)
2286     {
2287       output_position = p->start_position + end_vector[line];
2288       if (p->start_position - col_sep_length == chars_per_margin)
2289         output_position -= col_sep_length;
2290     }
2291
2292   return TRUE;
2293 }
2294
2295 /* Convert a character to the proper format and return the number of
2296    characters in the resulting clump.  Increment input_position by
2297    the width of the clump.
2298
2299    Tabs are converted to clumps of spaces.
2300    Nonprintable characters may be converted to clumps of escape
2301    sequences or control prefixes.
2302
2303    Note: the width of a clump is not necessarily equal to the number of
2304    characters in clump_buff.  (e.g, the width of '\b' is -1, while the
2305    number of characters is 1.) */
2306
2307 static int
2308 char_to_clump (int c)
2309 {
2310   register int *s = clump_buff;
2311   register int i;
2312   char esc_buff[4];
2313   int width;
2314   int chars;
2315
2316   if (c == input_tab_char)
2317     {
2318       width = TAB_WIDTH (chars_per_input_tab, input_position);
2319
2320       if (untabify_input)
2321         {
2322           for (i = width; i; --i)
2323             *s++ = ' ';
2324           chars = width;
2325         }
2326       else
2327         {
2328           *s = c;
2329           chars = 1;
2330         }
2331
2332     }
2333   else if (!ISPRINT (c))
2334     {
2335       if (use_esc_sequence)
2336         {
2337           width = 4;
2338           chars = 4;
2339           *s++ = '\\';
2340           sprintf (esc_buff, "%03o", c);
2341           for (i = 0; i <= 2; ++i)
2342             *s++ = (int) esc_buff[i];
2343         }
2344       else if (use_cntrl_prefix)
2345         {
2346           if (c < 0200)
2347             {
2348               width = 2;
2349               chars = 2;
2350               *s++ = '^';
2351               *s++ = c ^ 0100;
2352             }
2353           else
2354             {
2355               width = 4;
2356               chars = 4;
2357               *s++ = '\\';
2358               sprintf (esc_buff, "%03o", c);
2359               for (i = 0; i <= 2; ++i)
2360                 *s++ = (int) esc_buff[i];
2361             }
2362         }
2363       else if (c == '\b')
2364         {
2365           width = -1;
2366           chars = 1;
2367           *s = c;
2368         }
2369       else
2370         {
2371           width = 0;
2372           chars = 1;
2373           *s = c;
2374         }
2375     }
2376   else
2377     {
2378       width = 1;
2379       chars = 1;
2380       *s = c;
2381     }
2382
2383   input_position += width;
2384   return chars;
2385 }
2386
2387 /* We've just printed some files and need to clean up things before
2388    looking for more options and printing the next batch of files.
2389
2390    Free everything we've xmalloc'ed, except `header'. */
2391
2392 static void
2393 cleanup (void)
2394 {
2395   if (number_buff)
2396     free (number_buff);
2397   if (clump_buff)
2398     free (clump_buff);
2399   if (column_vector)
2400     free (column_vector);
2401   if (line_vector)
2402     free (line_vector);
2403   if (end_vector)
2404     free (end_vector);
2405   if (buff)
2406     free (buff);
2407 }
2408 \f
2409 /* Complain, print a usage message, and die. */
2410
2411 static void
2412 usage (int status)
2413 {
2414   if (status != 0)
2415     fprintf (stderr, _("Try `%s --help' for more information.\n"),
2416              program_name);
2417   else
2418     {
2419       printf (_("\
2420 Usage: %s [OPTION]... [FILE]...\n\
2421 "),
2422               program_name);
2423
2424       printf (_("\
2425 Paginate or columnate FILE(s) for printing.\n\
2426 \n\
2427   +FIRST_PAGE[:LAST_PAGE]\n\
2428                     begin [stop] printing with page FIRST_[LAST_]PAGE\n\
2429   -COLUMN           produce COLUMN-column output and print columns down,\n\
2430                     unless -a is used. Balance number of lines in the\n\
2431                     columns on each page.\n\
2432   -a                print columns across rather than down, used together\n\
2433                     with -COLUMN\n\
2434   -c                use hat notation (^G) and octal backslash notation\n\
2435   -d                double space the output\n\
2436   -e[CHAR[WIDTH]]   expand input CHARs (TABs) to tab WIDTH (8)\n\
2437   -F, -f            use form feeds instead of newlines to separate pages\n\
2438                     (by a 3-line page header with -f or a 5-line header\n\
2439                     and trailer without -f)\n\
2440   -h HEADER         use a centered HEADER instead of filename in page headers\n\
2441                     with long headers left-hand-side truncation may occur\n\
2442                     -h \"\" prints a blank line. Don't use -h\"\"\n\
2443   -i[CHAR[WIDTH]]   replace spaces with CHARs (TABs) to tab WIDTH (8)\n\
2444   -j                merge full lines, turns off -w line truncation, no column\n\
2445                     alignment, -s[STRING] sets separators\n\
2446   -l PAGE_LENGTH    set the page length to PAGE_LENGTH (66) lines\n\
2447                     (default number of lines of text 56, with -f 63)\n"));
2448       printf (_("\
2449   -m                print all files in parallel, one in each column,\n\
2450                     truncate lines, but join lines of full length with -j\n\
2451   -n[SEP[DIGITS]]   number lines, use DIGITS (5) digits, then SEP (TAB)\n\
2452                     default counting starts with 1st line of input file\n\
2453   -N NUMBER         start counting with NUMBER at 1st line of first\n\
2454                     page printed (see +FIRST_PAGE)\n\
2455   -o MARGIN         offset each line with MARGIN spaces (do not affect -w)\n\
2456   -r                inhibit warning when a file cannot be opened\n\
2457   -s[STRING]        separate columns by an optional STRING, don't use\n\
2458                     -s \"STRING\", -s only: No separator used (same as -s\"\"),\n\
2459                     without -s: Default separator \'TAB\' with -j and \'space\'\n\
2460                     otherwise (same as -s\" \")\n\
2461   -t                inhibit page headers and trailers\n\
2462   -T                inhibit page headers and trailers, eliminate any page\n\
2463                     layout by form feeds set in input files\n\
2464   -v                use octal backslash notation\n\
2465   -w PAGE_WIDTH     set page width to PAGE_WIDTH (72) columns, truncate\n\
2466                     lines (see also -j option)\n\
2467   --help            display this help and exit\n\
2468   --version         output version information and exit\n\
2469 \n\
2470 -T implied by -l nn when nn <= 10 or <= 3 with -f. With no FILE, or when\n\
2471 FILE is -, read standard input.\n\
2472 "));
2473       puts (_("\nReport bugs to <textutils-bugs@gnu.org>."));
2474     }
2475   exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
2476 }