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