1 /* pr -- convert text files for printing.
2 Copyright (C) 88, 91, 1995-1999 Free Software Foundation, Inc.
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)
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.
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. */
18 /* By Pete TerMaat, with considerable refinement by Roland Huebner. */
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
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.
30 Improve the printing of control prefixes.
32 Expand the filename in the centered header line to a full pathname.
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
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
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
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
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
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.
90 Capital letter options dominate small letter ones.
92 Some of the option-arguments cannot be specified as separate arguments
93 from the preceding option letter (already stated in POSIX specification).
95 Form feeds in the input cause page breaks in the output. Multiple
96 form feeds produce empty pages.
98 +FIRST_PAGE[:LAST_PAGE], --pages=FIRST_PAGE[:LAST_PAGE]
99 begin [stop] printing with page FIRST_[LAST_]PAGE
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.
106 -a, --across Print columns across rather than down, used
107 together with -COLUMN. The input
112 will be printed with `-a -3' as
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.
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.
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.
134 -d, --double-space Double space the output.
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.
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.
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
153 -h "" now prints a blank line header. -h"" shows an error.
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)
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.
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
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.
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.
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.
190 Together with -J option join lines of full length and
191 set separators when -S option is used.
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
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
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).
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
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.
228 -r, --no-file-warnings
229 Omit warning when a file cannot be opened.
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.
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
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.
253 -t, --omit-header Do not print headers or footers but retain form
254 feeds set in the input files.
256 -T, --omit-pagination
257 Do not print headers or footers, eliminate any pagination
258 by form feeds set in the input files.
260 -v, --show-nonprinting
261 Print unprintable characters as escape sequences. Use
262 octal backslash notation. Control-G becomes \007.
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
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
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 .
288 With/without -W PAGE_WIDTH the header line is always
289 truncated to avoid line overflow.
291 (In pr versions newer than 1.14 -S option does no longer
301 #include <sys/types.h>
305 #include "long-options.h"
308 /* The official name of this program (e.g., no `g' prefix). */
309 #define PROGRAM_NAME "pr"
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. */
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
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
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.
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().
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().
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[].
347 lines_stored Number of lines in this column which are stored in
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.
355 start_position The horizontal position we want to be in before we
356 print the first character in this column.
358 numbered True means precede this column with a line number. */
362 FILE *fp; /* Input stream for this column. */
363 char *name; /* File name. */
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. */
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. */
380 int full_page_printed; /* True means printed without a FF found. */
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
388 typedef struct COLUMN COLUMN;
390 #define NULLCOL (COLUMN *)0
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,
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));
422 /* The name under which this program was invoked. */
425 /* All of the columns to print. */
426 static COLUMN *column_vector;
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]. */
434 /* Index of the position in buff where the next character
436 static int buff_current;
438 /* The number of characters in buff.
439 Used for allocation of buff and to detect overflow of buff. */
440 static int buff_allocated;
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;
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
453 static int *end_vector;
455 /* (-m) True means we're printing multiple files in parallel. */
456 static int parallel_files = FALSE;
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;
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;
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
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. */
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;
478 /* (-t|-T) False means we aren't printing headers and footers. */
479 static int extremities = TRUE;
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;
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;
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;
494 /* (-f) True means use formfeeds instead of newlines to separate pages. */
495 static int use_form_feed = FALSE;
497 /* True means we have read the standard input. */
498 static int have_read_stdin = FALSE;
500 /* True means the -a flag has been given. */
501 static int print_across_flag = FALSE;
503 /* True means we're printing one file in multiple (>1) downward columns. */
504 static int storing_columns = TRUE;
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;
512 /* (-l) Number of lines on a page, including header and footer lines. */
513 static int lines_per_page = 66;
515 /* Number of lines in the header and footer can be reset to 0 using
517 static int lines_per_header = 5;
518 static int lines_per_body;
519 static int lines_per_footer = 5;
521 /* (-w|-W) Width in characters of the page. Does not include the width of
523 static int chars_per_line = 72;
525 /* (-w|W) True means we truncate lines longer than chars_per_column. */
526 static int truncate_lines = FALSE;
528 /* (-J) True means we join lines without any line truncation. -J
529 dominates -w option. */
530 static int join_lines = FALSE;
532 /* Number of characters in a column. Based on col_sep_length and
534 static int chars_per_column;
536 /* (-e) True means convert tabs to spaces on input. */
537 static int untabify_input = FALSE;
539 /* (-e) The input tab character. */
540 static char input_tab_char = '\t';
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;
546 /* (-i) True means convert spaces to tabs on output. */
547 static int tabify_output = FALSE;
549 /* (-i) The output tab character. */
550 static char output_tab_char = '\t';
552 /* (-i) The width of the output tab. */
553 static int chars_per_output_tab = 8;
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;
560 /* (-o) Number of spaces in the left margin (tabs used when possible). */
561 static int chars_per_margin = 0;
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;
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;
575 /* Count number of failed opens so we can exit with nonzero
576 status if there were any. */
577 static int failed_opens = 0;
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_)))
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_))
587 /* (-NNN) Number of columns of text to print. */
588 static int columns = 1;
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;
595 /* Number of files open (not closed, not on hold). */
596 static int files_ready_to_read = 0;
598 /* Current page number. Displayed in header. */
599 static int page_number;
601 /* Current line number. Displayed when -n flag is specified.
603 When printing files in parallel (-m flag), line numbering is as follows:
607 When printing files across (-a flag), ...
611 Otherwise, line numbering is as follows:
614 static int line_number;
616 /* With line_number overflow, we use power_10 to cut off the higher-order
617 digits of the line_number */
620 /* (-n) True means lines should be preceded by numbers. */
621 static int numbered_lines = FALSE;
623 /* (-n) Character which follows each line number. */
624 static char number_separator = '\t';
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;
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;
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;
639 /* (-n) Width in characters of a line number. */
640 static int chars_per_number = 5;
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;
647 /* Buffer sprintf uses to format a line number. */
648 static char *number_buff;
650 /* (-v) True means unprintable characters are printed as escape sequences.
651 control-g becomes \007. */
652 static int use_esc_sequence = FALSE;
654 /* (-c) True means unprintable characters are printed as control prefixes.
655 control-g becomes ^G. */
656 static int use_cntrl_prefix = FALSE;
658 /* (-d) True means output is double spaced. */
659 static int double_space = FALSE;
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;
665 /* (-r) True means don't complain if we can't open a file. */
666 static int ignore_failed_opens = FALSE;
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;
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";
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;
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;
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;
692 /* (-h) String of characters used in place of the filename in the header. */
693 static char *custom_header;
695 /* String containing the date, filename or custom header, and "Page ". */
698 static int *clump_buff;
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
704 static int last_line = FALSE;
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;
710 static struct option const long_options[] =
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'},
739 /* Return the number of columns that have either an open file or
743 cols_ready_to_print (void)
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))
758 /* Estimate first_ / last_page_number
759 using option +FIRST_PAGE:LAST_PAGE */
762 first_last_page (char *pages)
768 error (0, 0, _("`--pages' invalid range of page numbers: `%s'"), pages);
772 str1 = strchr (pages, ':');
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'"),
782 first_page_number = (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'"),
794 last_page_number = (int) tmp_long;
797 if (first_page_number > last_page_number)
798 error (EXIT_FAILURE, 0,
799 _("`--pages' starting page number is larger than ending page number"));
802 /* Estimate length of col_sep_string with option -S[STRING] */
805 separator_string (const char *optarg_S)
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);
813 main (int argc, char **argv)
818 int old_options = FALSE;
823 program_name = argv[0];
824 setlocale (LC_ALL, "");
825 bindtextdomain (PACKAGE, LOCALEDIR);
826 textdomain (PACKAGE);
828 parse_long_options (argc, argv, "pr", GNU_PACKAGE, VERSION,
829 "Pete TerMaat and Roland Huebner", usage);
832 file_names = (argc > 1
833 ? (char **) xmalloc ((argc - 1) * sizeof (char *))
838 c = getopt_long (argc, argv,
839 "-0123456789abcde::fFh:i::Jl:mn::N:o:rs::S::tTvw:W:",
841 if (c == 1) /* Non-option argument. */
847 /* long option --page dominates old `+FIRST_PAGE ...' */
848 if (first_page_number > 0 || last_page_number > 0)
855 file_names[n_files++] = optarg;
862 accum = accum * 10 + c - '0';
870 explicit_columns = TRUE;
884 case 0: /* getopt long option */
887 case CHAR_MAX + 1: /* --pages=FIRST_PAGE[:LAST_PAGE] */
888 { /* dominates old opt +... */
890 first_last_page (optarg);
892 error (EXIT_FAILURE, 0,
893 _("`--pages=FIRST_PAGE[:LAST_PAGE]' missing argument"));
897 case CHAR_MAX + 2: /* --columns=COLUMN */
900 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
901 || tmp_long <= 0 || tmp_long > INT_MAX)
903 error (EXIT_FAILURE, 0,
904 _("`--columns=COLUMN' invalid number of columns: `%s'"),
907 columns = (int) tmp_long;
912 print_across_flag = TRUE;
913 storing_columns = FALSE;
916 balance_columns = TRUE;
919 use_cntrl_prefix = TRUE;
926 getoptarg (optarg, 'e', &input_tab_char,
927 &chars_per_input_tab);
928 /* Could check tab width > 0. */
929 untabify_input = TRUE;
933 use_form_feed = TRUE;
936 custom_header = optarg;
937 standard_header = FALSE;
941 getoptarg (optarg, 'i', &output_tab_char,
942 &chars_per_output_tab);
943 /* Could check tab width > 0. */
944 tabify_output = TRUE;
952 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
953 || tmp_long <= 0 || tmp_long > INT_MAX)
955 error (EXIT_FAILURE, 0,
956 _("`-l PAGE_LENGTH' invalid number of lines: `%s'"),
959 lines_per_page = (int) tmp_long;
963 parallel_files = TRUE;
964 storing_columns = FALSE;
967 numbered_lines = TRUE;
969 getoptarg (optarg, 'n', &number_separator,
976 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
977 || tmp_long > INT_MAX)
979 error (EXIT_FAILURE, 0,
980 _("`-N NUMBER' invalid starting line number: `%s'"),
983 start_line_num = (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;
997 ignore_failed_opens = TRUE;
1002 if (!use_col_separator && optarg)
1003 separator_string (optarg);
1007 /* Reset an additional input of -s, -S dominates -s */
1008 col_sep_string = "";
1010 use_col_separator = TRUE;
1012 separator_string (optarg);
1015 extremities = FALSE;
1019 extremities = FALSE;
1023 use_esc_sequence = TRUE;
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;
1038 old_w = FALSE; /* dominates -w */
1039 truncate_lines = TRUE;
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;
1055 /* Now we can set a reasonable initial value: */
1056 if (first_page_number == 0)
1057 first_page_number = 1;
1059 if (parallel_files && explicit_columns)
1060 error (EXIT_FAILURE, 0,
1061 _("Cannot specify number of columns when printing in parallel."));
1063 if (parallel_files && print_across_flag)
1064 error (EXIT_FAILURE, 0,
1065 _("Cannot specify both printing across and printing in parallel."));
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. */
1075 if (parallel_files || explicit_columns)
1078 truncate_lines = TRUE;
1080 /* adapt HP-UX and SunOS: -s = no separator;
1082 use_col_separator = TRUE;
1085 /* old -w sets width with columns only
1089 else if (!use_col_separator)
1091 /* No -S option read */
1092 if (old_s && (parallel_files || explicit_columns))
1094 if (!truncate_lines)
1096 /* old -s (without -w and -W) annuls column alignment,
1097 uses fields, activate -J */
1099 if (col_sep_length > 0)
1101 use_col_separator = TRUE;
1105 /* adapt HP-UX and SunOS: -s = no separator;
1107 use_col_separator = TRUE;
1112 for (; optind < argc; optind++)
1114 file_names[n_files++] = argv[optind];
1119 /* No file arguments specified; read from standard input. */
1120 print_files (0, NULL);
1125 print_files (n_files, file_names);
1129 for (i = 0; i < n_files; i++)
1130 print_files (1, &file_names[i]);
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);
1145 /* Parse options of the form -scNNN.
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
1152 getoptarg (char *arg, char switch_char, char *character, int *number)
1154 if (!ISDIGIT (*arg))
1155 *character = *arg++;
1159 if (xstrtol (arg, NULL, 10, &tmp_long, "") != LONGINT_OK
1160 || tmp_long <= 0 || tmp_long > INT_MAX)
1163 _("`-%c' extra characters or invalid number in the argument: `%s'"),
1167 *number = (int) tmp_long;
1171 /* Set parameters related to formatting. */
1174 init_parameters (int number_of_files)
1176 int chars_used_by_number = 0;
1180 lines_per_header = 3;
1181 lines_per_footer = 0;
1184 lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
1185 if (lines_per_body <= 0)
1187 extremities = FALSE;
1190 if (extremities == FALSE)
1191 lines_per_body = lines_per_page;
1194 lines_per_body = lines_per_body / 2;
1196 /* If input is stdin, cannot print parallel files. BSD dumps core
1198 if (number_of_files == 0)
1199 parallel_files = FALSE;
1202 columns = number_of_files;
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;
1209 /* Tabification is assumed for multiple columns. */
1212 if (!use_col_separator)
1214 /* Use default separator */
1216 col_sep_string = line_separator;
1218 col_sep_string = column_separator;
1221 use_col_separator = TRUE;
1223 /* It's rather pointless to define a TAB separator with column
1225 else if (!join_lines && *col_sep_string == '\t')
1226 col_sep_string = column_separator;
1228 truncate_lines = TRUE;
1229 untabify_input = TRUE;
1230 tabify_output = TRUE;
1233 storing_columns = FALSE;
1235 /* -J dominates -w in any case */
1237 truncate_lines = FALSE;
1242 int chars_per_default_tab = 8;
1244 line_count = start_line_num;
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); */
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);
1256 number_width = chars_per_number + 1;
1258 /* The number is part of the column width unless we are
1259 printing files in parallel. */
1261 chars_used_by_number = number_width;
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;
1270 chars_per_column = (chars_per_line - chars_used_by_number -
1271 (columns - 1) * col_sep_length) / columns;
1273 if (chars_per_column < 1)
1274 error (EXIT_FAILURE, 0, _("page width too narrow"));
1278 if (number_buff != NULL)
1280 number_buff = (char *) xmalloc (2 * chars_per_number);
1283 /* Pick the maximum between the tab width and the width of an
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)
1290 clump_buff = (int *) xmalloc ((chars_per_input_tab > 8
1291 ? chars_per_input_tab : 8) * sizeof (int));
1294 /* Open the necessary files,
1295 maintaining a COLUMN structure for each column.
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,
1302 With each column/file p, p->full_page_printed is initialized,
1303 see also open_file. */
1306 init_fps (int number_of_files, char **av)
1315 if (column_vector != NULLCOL)
1316 free ((char *) column_vector);
1317 column_vector = (COLUMN *) xmalloc (columns * sizeof (COLUMN));
1321 files_left = number_of_files;
1322 for (p = column_vector; files_left--; ++p, ++av)
1324 if (open_file (*av, p) == 0)
1332 init_header ("", -1);
1337 if (number_of_files > 0)
1339 if (open_file (*av, p) == 0)
1341 init_header (*av, fileno (p->fp));
1342 p->lines_stored = 0;
1346 p->name = _("standard input");
1348 have_read_stdin = TRUE;
1350 p->full_page_printed = FALSE;
1352 init_header ("", -1);
1353 p->lines_stored = 0;
1356 firstname = p->name;
1358 for (i = columns - 1, ++p; i; --i, ++p)
1360 p->name = firstname;
1363 p->full_page_printed = FALSE;
1364 p->lines_stored = 0;
1367 files_ready_to_read = total_files;
1371 /* Determine print_func and char_func, the functions
1372 used by each column for printing and/or storing.
1374 Determine the horizontal position desired when we begin
1375 printing a column (p->start_position). */
1383 h = chars_per_margin;
1385 if (!truncate_lines)
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;
1395 h_next = h + chars_per_column;
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;
1402 /* This loop takes care of all but the rightmost column. */
1404 for (p = column_vector, i = 1; i < columns; ++p, ++i)
1406 if (storing_columns) /* One file, multi columns down. */
1408 p->char_func = store_char;
1409 p->print_func = print_stored;
1412 /* One file, multi columns across; or parallel files. */
1414 p->char_func = print_char;
1415 p->print_func = read_line;
1418 /* Number only the first column when printing files in
1420 p->numbered = numbered_lines && (!parallel_files || i == 1);
1421 p->start_position = h;
1423 /* If we don't truncate lines, all start_positions are
1424 ANYWHERE, except the first column's start_position when
1427 if (!truncate_lines)
1434 h = h_next + col_sep_length;
1435 h_next = h + chars_per_column;
1439 /* The rightmost column.
1441 Doesn't need to be stored unless we intend to balance
1442 columns on the last page. */
1443 if (storing_columns && balance_columns)
1445 p->char_func = store_char;
1446 p->print_func = print_stored;
1450 p->char_func = print_char;
1451 p->print_func = read_line;
1454 p->numbered = numbered_lines && (!parallel_files || i == 1);
1455 p->start_position = h;
1458 /* Open a file. Return nonzero if successful, zero if failed.
1460 With each file p, p->full_page_printed is initialized,
1461 see also init_fps. */
1464 open_file (char *name, COLUMN *p)
1466 if (STREQ (name, "-"))
1468 p->name = _("standard input");
1470 have_read_stdin = 1;
1475 p->fp = fopen (name, "r");
1480 if (!ignore_failed_opens)
1481 error (0, errno, "%s", name);
1485 p->full_page_printed = FALSE;
1490 /* Close the file in P.
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. */
1496 close_file (COLUMN *p)
1501 if (p->status == CLOSED)
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);
1508 if (!parallel_files)
1510 for (q = column_vector, i = columns; i; ++q, --i)
1513 if (q->lines_stored == 0)
1515 q->lines_to_print = 0;
1522 p->lines_to_print = 0;
1525 --files_ready_to_read;
1528 /* Put a file on hold until we start a new page,
1529 since we've hit a form feed.
1531 If we aren't dealing with parallel files, we must change the
1532 status of all columns in the column list. */
1535 hold_file (COLUMN *p)
1540 if (!parallel_files)
1541 for (q = column_vector, i = columns; i; ++q, --i)
1543 if (storing_columns)
1544 q->status = FF_FOUND;
1546 q->status = ON_HOLD;
1549 p->status = ON_HOLD;
1551 p->lines_to_print = 0;
1552 --files_ready_to_read;
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. */
1564 for (p = column_vector; i; --i, ++p)
1565 if (p->status == ON_HOLD)
1568 files_ready_to_read++;
1571 if (storing_columns)
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;
1577 files_ready_to_read = 1;
1581 /* Print a single file, or multiple files in parallel.
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
1588 Print the file(s). */
1591 print_files (int number_of_files, char **av)
1593 init_parameters (number_of_files);
1594 if (init_fps (number_of_files, av))
1596 if (storing_columns)
1599 if (first_page_number > 1)
1601 if (!skip_to_page (first_page_number))
1604 page_number = first_page_number;
1611 line_number = line_count;
1612 while (print_page ())
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
1620 /* Initialize header information.
1621 If DESC is non-negative, it is a file descriptor open to
1622 FILENAME for reading.
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. */
1630 init_header (char *filename, int desc)
1632 int chars_per_middle, chars_free, lhs_blanks, rhs_blanks;
1634 char *no_middle = "";
1638 char *datim = "- Date/Time --";
1640 if (filename == NULL)
1645 header = (char *) xmalloc (chars_per_line + 1);
1647 if (!standard_header && *custom_header == '\0')
1648 sprintf (header, "%s", " "); /* blank line header */
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];
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);
1659 tmptr = localtime (&st.st_mtime);
1660 strftime (t_buf, T_BUF_SIZE, T_BUF_FMT, tmptr);
1662 chars_per_middle = chars_per_line - CHARS_FOR_DATE_AND_PAGE;
1663 if (chars_per_middle < 3)
1665 header_text = no_middle; /* Nothing free for a heading */
1671 header_text = standard_header ? f : custom_header;
1672 chars_free = chars_per_middle - (int) strlen (header_text);
1675 lhs_blanks = chars_free / 2; /* text not truncated */
1676 rhs_blanks = chars_free - lhs_blanks;
1679 { /* lhs truncation */
1680 header_text = header_text - chars_free + 2;
1687 sprintf (header, _("%s%*s%s%*sPage"), (test_suite ? datim : t_buf),
1688 lhs_blanks, " ", header_text, rhs_blanks, " ");
1692 /* Set things up for printing a page
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 */
1708 if (storing_columns)
1711 for (j = columns - 1, p = column_vector; j; --j, ++p)
1713 p->lines_to_print = p->lines_stored;
1717 if (balance_columns)
1719 p->lines_to_print = p->lines_stored;
1721 /* Since we're not balancing columns, we don't need to store
1722 the rightmost column. Read it straight from the file. */
1725 if (p->status == OPEN)
1727 p->lines_to_print = lines_per_body;
1730 p->lines_to_print = 0;
1734 for (j = columns, p = column_vector; j; --j, ++p)
1735 if (p->status == OPEN)
1737 p->lines_to_print = lines_per_body;
1740 p->lines_to_print = 0;
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. */
1748 align_column (COLUMN *p)
1750 padding_not_printed = p->start_position;
1751 if (padding_not_printed - col_sep_length > 0)
1753 pad_across_to (padding_not_printed - col_sep_length);
1754 padding_not_printed = ANYWHERE;
1757 if (use_col_separator)
1758 print_sep_string ();
1761 add_line_number (p);
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
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. */
1779 int lines_left_on_page;
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. */
1793 if (cols_ready_to_print () == 0)
1797 print_a_header = TRUE;
1799 /* Don't pad unless we know a page was printed. */
1800 pad_vertically = FALSE;
1803 lines_left_on_page = lines_per_body;
1805 lines_left_on_page *= 2;
1807 while (lines_left_on_page > 0 && cols_ready_to_print () > 0)
1809 output_position = 0;
1810 spaces_not_printed = 0;
1811 separators_not_printed = 0;
1812 pad_vertically = FALSE;
1813 align_empty_cols = FALSE;
1816 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1819 if (p->lines_to_print > 0 || p->status == FF_FOUND)
1822 padding_not_printed = p->start_position;
1823 if (!(p->print_func) (p))
1824 read_rest_of_line (p);
1825 pv |= pad_vertically;
1827 --p->lines_to_print;
1828 if (p->lines_to_print <= 0)
1830 if (cols_ready_to_print () <= 0)
1834 /* File p changed its status to ON_HOLD or CLOSED */
1835 if (parallel_files && p->status != OPEN)
1838 align_empty_cols = TRUE;
1839 else if (p->status == CLOSED ||
1840 (p->status == ON_HOLD && FF_only))
1844 else if (parallel_files)
1846 /* File status ON_HOLD or CLOSED */
1848 align_empty_cols = TRUE;
1853 /* We need it also with an empty column */
1854 if (use_col_separator)
1855 ++separators_not_printed;
1861 --lines_left_on_page;
1864 if (cols_ready_to_print () <= 0 && !extremities)
1867 if (double_space && pv)
1870 --lines_left_on_page;
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;
1879 pad_vertically = pv;
1881 if (pad_vertically && extremities)
1882 pad_down (lines_left_on_page + lines_per_footer);
1883 else if (keep_FF && print_a_FF)
1889 if (last_page_number && page_number > last_page_number)
1890 return FALSE; /* Stop printing with LAST_PAGE */
1892 reset_status (); /* Change ON_HOLD to OPEN. */
1894 return TRUE; /* More pages to go. */
1897 /* Allocate space for storing columns.
1899 This is necessary when printing multiple columns from a single file.
1900 Lines are stored consecutively in buff, separated by '\0'.
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
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. */
1912 init_store_cols (void)
1914 int total_lines = lines_per_body * columns;
1915 int chars_if_truncate = total_lines * (chars_per_column + 1);
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 *));
1922 if (end_vector != NULL)
1923 free ((int *) end_vector);
1924 end_vector = (int *) xmalloc (total_lines * sizeof (int *));
1928 buff_allocated = (use_col_separator
1929 ? 2 * chars_if_truncate
1930 : chars_if_truncate); /* Tune this. */
1931 buff = (char *) xmalloc (buff_allocated);
1934 /* Store all but the rightmost column.
1935 (Used when printing a single file in multiple downward columns)
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
1947 store_columns (void)
1952 int last_col; /* The rightmost column which will be saved in buff */
1958 if (balance_columns)
1961 last_col = columns - 1;
1963 for (i = 1, p = column_vector; i <= last_col; ++i, ++p)
1964 p->lines_stored = 0;
1966 for (i = 1, p = column_vector; i <= last_col && files_ready_to_read;
1969 p->current_line = line;
1970 for (j = lines_per_body; j && files_ready_to_read; --j)
1972 if (p->status == OPEN) /* Redundant. Clean up. */
1977 read_rest_of_line (p);
1979 if (p->status == OPEN
1980 || buff_start != buff_current)
1983 line_vector[line] = buff_start;
1984 end_vector[line++] = input_position;
1985 buff_start = buff_current;
1990 /* Keep track of the location of the last char in buff. */
1991 line_vector[line] = buff_start;
1993 if (balance_columns && p->lines_stored != lines_per_body)
1998 balance (int total_stored)
2004 for (i = 1, p = column_vector; i <= columns; ++i, ++p)
2006 lines = total_stored / columns;
2007 if (i <= total_stored % columns)
2010 p->lines_stored = lines;
2011 p->current_line = first_line;
2013 first_line += lines;
2017 /* Store a character in the buffer. */
2022 if (buff_current >= buff_allocated)
2024 /* May be too generous. */
2025 buff_allocated = 2 * buff_allocated;
2026 buff = (char *) xrealloc (buff, buff_allocated * sizeof (char));
2028 buff[buff_current++] = (char) c;
2032 add_line_number (COLUMN *p)
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);
2044 left_cut = line_number % power_10;
2045 sprintf (number_buff, "%0*d", chars_per_number, left_cut);
2049 for (i = chars_per_number; i > 0; i--)
2050 (p->char_func) ((int) *s++);
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')
2059 i = number_width - chars_per_number;
2061 (p->char_func) ((int) ' ');
2064 (p->char_func) ((int) number_separator);
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. */
2071 (p->char_func) ((int) number_separator);
2072 if (number_separator == '\t')
2073 output_position = POS_AFTER_TAB (chars_per_output_tab,
2077 if (truncate_lines && !parallel_files)
2078 input_position += number_width;
2081 /* Print (or store) padding until the current horizontal position
2085 pad_across_to (int position)
2087 register int h = output_position;
2090 spaces_not_printed = position - output_position;
2093 while (++h <= position)
2095 output_position = position;
2099 /* Pad to the bottom of the page.
2101 If the user has requested a formfeed, use one.
2102 Otherwise, use newlines. */
2105 pad_down (int lines)
2112 for (i = lines; i; --i)
2116 /* Read the rest of the line.
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. */
2123 read_rest_of_line (COLUMN *p)
2128 while ((c = getc (f)) != '\n')
2132 if ((c = getc (f)) != '\n')
2147 /* Read a line with skip_to_page.
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). */
2157 skip_read (COLUMN *p, int column_number)
2161 int i, single_ff = FALSE;
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')
2171 p->full_page_printed = FALSE;
2173 /* 1st character a FF means a single FF without any printable
2174 characters. Don't count it as a line with -n option. */
2178 /* Preparing for a FF-coincidence: Maybe we finish that page
2179 without a FF found */
2181 p->full_page_printed = TRUE;
2187 /* No FF-coincidence possible,
2188 no catching up of a FF-coincidence with next page */
2191 if (!parallel_files)
2192 for (q = column_vector, i = columns; i; ++q, --i)
2193 q->full_page_printed = FALSE;
2195 p->full_page_printed = FALSE;
2198 if ((c = getc (f)) != '\n')
2212 if ((!parallel_files || column_number == 1) && !single_ff)
2216 /* If we're tabifying output,
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. */
2223 print_white_space (void)
2226 register int h_old = output_position;
2227 register int goal = h_old + spaces_not_printed;
2229 while (goal - h_old > 1
2230 && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal)
2232 putchar (output_tab_char);
2235 while (++h_old <= goal)
2238 output_position = goal;
2239 spaces_not_printed = 0;
2242 /* Print column separators.
2244 We keep a count until we know that we'll be printing a line,
2245 then print_sep_string() is called. */
2251 int l = col_sep_length;
2255 if (separators_not_printed <= 0)
2257 /* We'll be starting a line with chars_per_margin, anything else? */
2258 if (spaces_not_printed > 0)
2259 print_white_space ();
2263 for (; separators_not_printed > 0; --separators_not_printed)
2267 /* 3 types of sep_strings: spaces only, spaces and chars,
2271 /* We're tabifying output; consecutive spaces in
2272 sep_string may have to be converted to tabs */
2274 ++spaces_not_printed;
2278 if (spaces_not_printed > 0)
2279 print_white_space ();
2284 /* sep_string ends with some spaces */
2285 if (spaces_not_printed > 0)
2286 print_white_space ();
2291 /* Print (or store, depending on p->char_func) a clump of N
2295 print_clump (COLUMN *p, int n, int *clump)
2298 (p->char_func) (*clump++);
2301 /* Print a character.
2303 Update the following comment: process-char hasn't been used any
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. */
2317 ++spaces_not_printed;
2320 else if (spaces_not_printed > 0)
2321 print_white_space ();
2323 /* Nonprintables are assumed to have width 0, except '\b'. */
2335 /* Skip to page PAGE before printing.
2336 PAGE may be larger than total number of pages. */
2339 skip_to_page (int page)
2344 for (n = 1; n < page; ++n)
2346 for (i = 1; i < lines_per_body; ++i)
2348 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2349 if (p->status == OPEN)
2353 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2354 if (p->status == OPEN)
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;
2365 if (files_ready_to_read < 1)
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);
2373 return files_ready_to_read > 0;
2378 Formfeeds are assumed to use up two lines at the beginning of
2385 fprintf (stdout, "\n\n");
2387 output_position = 0;
2388 pad_across_to (chars_per_margin);
2389 print_white_space ();
2391 if (!standard_header && *custom_header == '\0')
2393 fprintf (stdout, "%s\n\n\n", header);
2397 fprintf (stdout, "%s%5d\n\n\n", header, page_number++);
2399 print_a_header = FALSE;
2400 output_position = 0;
2403 /* Print (or store, if p->char_func is store_char()) a line.
2405 Read a character to determine whether we have a line or not.
2406 (We may hit EOF, \n, or \f)
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.
2416 Print the clump which corresponds to the first character.
2418 Enter a loop and keep printing until an end of line condition
2419 exists, or until we exceed chars_per_column.
2421 Return FALSE if we exceed chars_per_column before reading
2422 an end of line character, TRUE otherwise. */
2425 read_line (COLUMN *p)
2427 register int c, chars;
2428 int last_input_position;
2432 /* Suppress `used before initialized' warning. */
2437 /* read 1st character in each line or any character succeeding a FF: */
2440 last_input_position = input_position;
2442 if (c == '\f' && p->full_page_printed)
2443 if ((c = getc (p->fp)) == '\n')
2445 p->full_page_printed = FALSE;
2450 if ((c = getc (p->fp)) != '\n')
2453 if (print_a_header && !storing_columns)
2455 pad_vertically = TRUE;
2468 chars = char_to_clump (c);
2471 if (truncate_lines && input_position > chars_per_column)
2473 input_position = last_input_position;
2477 if (p->char_func != store_char)
2479 pad_vertically = TRUE;
2481 if (print_a_header && !storing_columns)
2484 if (parallel_files && align_empty_cols)
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)
2492 separators_not_printed += 1;
2494 padding_not_printed = p->start_position;
2496 spaces_not_printed = chars_per_column;
2498 spaces_not_printed = 0;
2499 align_empty_cols = FALSE;
2502 if (padding_not_printed - col_sep_length > 0)
2504 pad_across_to (padding_not_printed - col_sep_length);
2505 padding_not_printed = ANYWHERE;
2508 if (use_col_separator)
2509 print_sep_string ();
2513 add_line_number (p);
2519 print_clump (p, chars, clump_buff);
2530 if ((c = getc (p->fp)) != '\n')
2541 last_input_position = input_position;
2542 chars = char_to_clump (c);
2543 if (truncate_lines && input_position > chars_per_column)
2545 input_position = last_input_position;
2549 print_clump (p, chars, clump_buff);
2553 /* Print a line from buff.
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
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.
2565 Return TRUE, meaning there is no need to call read_rest_of_line. */
2568 print_stored (COLUMN *p)
2573 int line = p->current_line++;
2574 register char *first = &buff[line_vector[line]];
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:
2583 xmalloc [xmalloc.c:94]
2584 init_store_cols [pr.c:1648]
2586 register char *last = &buff[line_vector[line + 1]];
2588 pad_vertically = TRUE;
2593 if (p->status == FF_FOUND)
2595 for (i = 1, q = column_vector; i <= columns; ++i, ++q)
2596 q->status = ON_HOLD;
2597 if (column_vector->lines_to_print <= 0)
2600 pad_vertically = FALSE;
2601 return TRUE; /* print a header only */
2605 if (padding_not_printed - col_sep_length > 0)
2607 pad_across_to (padding_not_printed - col_sep_length);
2608 padding_not_printed = ANYWHERE;
2611 if (use_col_separator)
2612 print_sep_string ();
2614 while (first != last)
2615 print_char (*first++);
2617 if (spaces_not_printed == 0)
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;
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.
2631 Tabs are converted to clumps of spaces.
2632 Nonprintable characters may be converted to clumps of escape
2633 sequences or control prefixes.
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.) */
2640 char_to_clump (int c)
2642 register int *s = clump_buff;
2647 int chars_per_c = 8;
2649 if (c == input_tab_char)
2650 chars_per_c = chars_per_input_tab;
2652 if (c == input_tab_char || c == '\t')
2654 width = TAB_WIDTH (chars_per_c, input_position);
2658 for (i = width; i; --i)
2669 else if (!ISPRINT (c))
2671 if (use_esc_sequence)
2676 sprintf (esc_buff, "%03o", c);
2677 for (i = 0; i <= 2; ++i)
2678 *s++ = (int) esc_buff[i];
2680 else if (use_cntrl_prefix)
2694 sprintf (esc_buff, "%03o", c);
2695 for (i = 0; i <= 2; ++i)
2696 *s++ = (int) esc_buff[i];
2719 input_position += width;
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.
2726 Free everything we've xmalloc'ed, except `header'. */
2736 free (column_vector);
2745 /* Complain, print a usage message, and die. */
2751 fprintf (stderr, _("Try `%s --help' for more information.\n"),
2756 Usage: %s [OPTION]... [FILE]...\n\
2761 Paginate or columnate FILE(s) for printing.\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\
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\
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"));
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\
2837 --help display this help and exit\n\
2838 --version output version information and exit\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\
2843 puts (_("\nReport bugs to <bug-textutils@gnu.org>."));
2845 exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);