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