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