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