.
[coreutils.git] / src / pr.c
bloba7e69e92a0547fb9ea01b4c8c53f4c7fe1421742
1 /* pr -- convert text files for printing.
2 Copyright (C) 88, 91, 95, 96, 1997, 1998 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)
7 any later version.
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 /* Author: Pete TerMaat. */
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
25 Ideas:
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.
33 Options:
35 +FIRST_PAGE[:LAST_PAGE]
36 begin [stop] printing with page FIRST_[LAST_]PAGE
38 -COLUMN Produce output that is COLUMN columns wide and print
39 columns down.
40 Balance columns on the last page is automatically set.
42 -a Print columns across rather than down. The input
43 one
44 two
45 three
46 four
47 will be printed as
48 one two three
49 four
51 -b Balance columns on the last page.
52 -b is no longer an independent option. It's always used
53 together with -COLUMN (unless -a is used) to get a
54 consistent formulation with "FF set by hand" in input
55 files. Each formfeed found terminates the number of lines
56 to be read with the actual page. The situation for
57 printing columns down is equivalent to that on the last
58 page. So we need a balancing.
60 We do not yet eliminate source text dealing with -COLUMN
61 only. Tune this if it proved to be a satisfactory
62 procedure.
64 Keeping -b as an underground option guarantees some
65 downward compatibility. Utilities using pr with -b
66 (a most frequently used form) still work as usual.
68 -c Print unprintable characters as control prefixes.
69 Control-g is printed as ^G.
71 -d Double space the output.
73 -e[c[k]] Expand tabs to spaces on input. Optional argument C
74 is the input tab character. (Default is `\t'.) Optional
75 argument K is the input tab character's width. (Default is 8.)
78 -f Use formfeeds instead of newlines to separate pages.
79 A three line HEADER is used, no TRAILER (without -f
80 both HEADER and TRAILER are made of five lines).
82 -h HEADER Replace the filename in the header with the string HEADER.
83 Checking and left-hand-side truncation of the length of the
84 standard and custom header string. A centered header is used.
85 The format of date and time has been shortened
86 to yy-mm-dd HH:MM to give place to a maximal filename
87 information.
88 -h "" now prints a blank line header. -h"" shows an error.
90 -i[c[k]] Replace spaces with tabs on output. Optional argument
91 C is the output tab character. (Default is `\t'.) Optional
92 argument K is the output tab character's width. (Default
93 is 8.)
95 -j Merge full lines, turns off -w line truncation, no column
96 alignment, -s[STRING] sets separators, works with all
97 column options (-COLUMN | -a -COLUMN | -m).
99 -l lines Set the page length to LINES. Default is 66.
101 -m Print files in parallel; pad_across_to align columns;
102 truncate lines and print separator strings;
103 Do it also with empty columns to get a continuous line
104 numbering and column marking by separators throughout
105 the whole merged file.
107 Empty pages in some input files produce empty columns
108 [marked by separators] in the common pages. Completely
109 empty common pages show no column separators at all.
111 The layout of a merged page is ruled by the largest form
112 feed distance of the single pages at that page. Shorter
113 columns will be filled up with empty lines.
115 Together with -j option join lines of full length and
116 in addition set separators when -s option is used.
118 -n[c[k]] Precede each column with a line number.
119 (With parallel files, precede each line with a line
120 number.) Optional argument C is the character to print
121 after each number. (Default `\t'.) Optional argument
122 k is the number of digits per line number. (Default 5.)
123 Default counting starts with 1st line of input file.
125 -N number Start counting with number at 1st line of first page
126 printed.
128 -o offset Offset each line with a margin OFFSET spaces wide.
129 Total page width is the size of this offset plus the
130 width set with `-w'.
132 -r Ignore files that can't be opened.
134 -s[STRING] Separate columns by any string STRING.
135 Don't use -s "STRING".
136 without -s: Default separator `TAB' with -j and `space'
137 otherwise (same as -s\" \"),
138 with -s only: no separator is used, same as -s"".
139 Quotes should be used with blanks and some shell active
140 characters.
142 -t Do not print headers or footers but retain form feeds
143 set in input files (some page layout is not changed).
145 -T Do not print headers or footers, eliminate form feeds
146 in input files.
148 -v Print unprintable characters as escape sequences.
149 Control-G becomes \007.
151 -w width Set the page width to WIDTH characters.
152 (In pr versions newer than 1.14 -s option does no longer
153 affect -w option.)
155 With/without -w width the header line is truncated.
156 Default is 72 characters.
157 With -w width text lines will be truncated, unless -j is
158 used. Together with one of the column options
159 (-COLUMN| -a -COLUMN| -m) column alignment is used.
160 Without -w PAGE_WIDTH
161 - but with one of the column options default truncation of
162 72 characters is used (to keep downward compatibility
163 and to simplify most frequently met column tasks).
164 Column alignment and column separators are used.
165 - and without any of the column options no line truncation
166 is used (to keep downward compatibility and to meet most
167 frequent tasks). That's equivalent to -w 72 -j .
171 #include <config.h>
173 #include <stdio.h>
174 #include <getopt.h>
175 #include <sys/types.h>
176 #include <time.h>
177 #include "system.h"
178 #include "error.h"
179 #include "xstrtol.h"
181 #ifndef TRUE
182 # define TRUE 1
183 # define FALSE 0
184 #endif
186 /* Used with start_position in the struct COLUMN described below.
187 If start_position == ANYWHERE, we aren't truncating columns and
188 can begin printing a column anywhere. Otherwise we must pad to
189 the horizontal position start_position. */
190 #define ANYWHERE 0
192 /* Each column has one of these structures allocated for it.
193 If we're only dealing with one file, fp is the same for all
194 columns.
196 The general strategy is to spend time setting up these column
197 structures (storing columns if necessary), after which printing
198 is a matter of flitting from column to column and calling
199 print_func.
201 Parallel files, single files printing across in multiple
202 columns, and single files printing down in multiple columns all
203 fit the same printing loop.
205 print_func Function used to print lines in this column.
206 If we're storing this column it will be
207 print_stored(), Otherwise it will be read_line().
209 char_func Function used to process characters in this column.
210 If we're storing this column it will be store_char(),
211 otherwise it will be print_char().
213 current_line Index of the current entry in line_vector, which
214 contains the index of the first character of the
215 current line in buff[].
217 lines_stored Number of lines in this column which are stored in
218 buff.
220 lines_to_print If we're storing this column, lines_to_print is
221 the number of stored_lines which remain to be
222 printed. Otherwise it is the number of lines
223 we can print without exceeding lines_per_body.
225 start_position The horizontal position we want to be in before we
226 print the first character in this column.
228 numbered True means precede this column with a line number. */
230 struct COLUMN
232 FILE *fp; /* Input stream for this column. */
233 char *name; /* File name. */
234 enum
236 OPEN,
237 FF_FOUND, /* used with -b option, set with \f, changed
238 to ON_HOLD after print_header */
239 ON_HOLD, /* Hit a form feed. */
240 CLOSED
242 status; /* Status of the file pointer. */
243 int (*print_func) (); /* Func to print lines in this col. */
244 void (*char_func) (); /* Func to print/store chars in this col. */
245 int current_line; /* Index of current place in line_vector. */
246 int lines_stored; /* Number of lines stored in buff. */
247 int lines_to_print; /* No. lines stored or space left on page. */
248 int start_position; /* Horizontal position of first char. */
249 int numbered;
250 int full_page_printed; /* True means printed without a FF found. */
252 /* p->full_page_printed controls a special case of "FF set by hand":
253 True means a full page has been printed without FF found. To avoid an
254 additional empty page we have to ignore a FF immediately following in
255 the next line. */
258 typedef struct COLUMN COLUMN;
260 #define NULLCOL (COLUMN *)0
262 static int char_to_clump PARAMS ((int c));
263 static int read_line PARAMS ((COLUMN *p));
264 static int print_page PARAMS ((void));
265 static int print_stored PARAMS ((COLUMN *p));
266 static int open_file PARAMS ((char *name, COLUMN *p));
267 static int skip_to_page PARAMS ((int page));
268 static void print_header PARAMS ((void));
269 static void pad_across_to PARAMS ((int position));
270 static void add_line_number PARAMS ((COLUMN *p));
271 static void getoptarg PARAMS ((char *arg, char switch_char, char *character,
272 int *number));
273 static void usage PARAMS ((int status));
274 static void print_files PARAMS ((int number_of_files, char **av));
275 static void init_parameters PARAMS ((int number_of_files));
276 static void init_header PARAMS ((char *filename, int desc));
277 static void init_store_cols PARAMS ((void));
278 static void store_columns PARAMS ((void));
279 static void balance PARAMS ((int total_stored));
280 static void store_char PARAMS ((int c));
281 static void pad_down PARAMS ((int lines));
282 static void read_rest_of_line PARAMS ((COLUMN *p));
283 static void skip_read PARAMS ((COLUMN *p, int column_number));
284 static void print_char PARAMS ((int c));
285 static void cleanup PARAMS ((void));
286 static void first_last_page PARAMS ((char *pages));
287 static void print_sep_string PARAMS ((void));
288 static void separator_string PARAMS ((const char *optarg_S));
290 /* The name under which this program was invoked. */
291 char *program_name;
293 /* All of the columns to print. */
294 static COLUMN *column_vector;
296 /* When printing a single file in multiple downward columns,
297 we store the leftmost columns contiguously in buff.
298 To print a line from buff, get the index of the first character
299 from line_vector[i], and print up to line_vector[i + 1]. */
300 static char *buff;
302 /* Index of the position in buff where the next character
303 will be stored. */
304 static int buff_current;
306 /* The number of characters in buff.
307 Used for allocation of buff and to detect overflow of buff. */
308 static int buff_allocated;
310 /* Array of indices into buff.
311 Each entry is an index of the first character of a line.
312 This is used when storing lines to facilitate shuffling when
313 we do column balancing on the last page. */
314 static int *line_vector;
316 /* Array of horizonal positions.
317 For each line in line_vector, end_vector[line] is the horizontal
318 position we are in after printing that line. We keep track of this
319 so that we know how much we need to pad to prepare for the next
320 column. */
321 static int *end_vector;
323 /* (-m) True means we're printing multiple files in parallel. */
324 static int parallel_files = FALSE;
326 /* (-m) True means a line starts with some empty columns (some files
327 already CLOSED or ON_HOLD) which we have to align. */
328 static int align_empty_cols;
330 /* (-m) True means we have not yet found any printable column in a line.
331 align_empty_cols = TRUE has to be maintained. */
332 static int empty_line;
334 /* (-m) False means printable column output precedes a form feed found.
335 Column align is done only once. No additional action with that form
336 feed.
337 True means we found only a form feed in a column. Maybe we have to do
338 some column align with that form feed. */
339 static int FF_only;
341 /* (-[0-9]+) True means we're given an option explicitly specifying
342 number of columns. Used to detect when this option is used with -m. */
343 static int explicit_columns = FALSE;
345 /* (-t|-T) False means we aren't printing headers and footers. */
346 static int extremities = TRUE;
348 /* (-t) True means we retain all FF set by hand in input files.
349 False is set with -T option. */
350 static int keep_FF = FALSE;
351 static int print_a_FF = FALSE;
353 /* True means we need to print a header as soon as we know we've got input
354 to print after it. */
355 static int print_a_header;
357 /* (-h) True means we're using the standard header rather than a
358 customized one specified by the -h flag. */
359 static int standard_header = TRUE;
361 /* (-f) True means use formfeeds instead of newlines to separate pages. */
362 static int use_form_feed = FALSE;
364 /* True means we have read the standard input. */
365 static int have_read_stdin = FALSE;
367 /* True means the -a flag has been given. */
368 static int print_across_flag = FALSE;
370 /* True means we're printing one file in multiple (>1) downward columns. */
371 static int storing_columns = TRUE;
373 /* (-b) True means balance columns on the last page as Sys V does. */
374 /* That's no longer an independent option. With storing_columns = TRUE
375 balance_columns = TRUE is used too (s. function init_parameters).
376 We get a consistent formulation with "FF set by hand" in input files. */
377 static int balance_columns = FALSE;
379 /* (-l) Number of lines on a page, including header and footer lines. */
380 static int lines_per_page = 66;
382 /* Number of lines in the header and footer can be reset to 0 using
383 the -t flag. */
384 static int lines_per_header = 5;
385 static int lines_per_body;
386 static int lines_per_footer = 5;
388 /* (-w) Width in characters of the page. Does not include the width of
389 the margin. */
390 static int chars_per_line = 72;
392 /* (-w) True means we truncate lines longer than chars_per_column. */
393 static int truncate_lines = FALSE;
395 /* (-j) True means we join lines without any line truncation. -j
396 dominates -w option. */
397 static int join_lines = FALSE;
399 /* Number of characters in a column. Based on col_sep_length and
400 page width. */
401 static int chars_per_column;
403 /* (-e) True means convert tabs to spaces on input. */
404 static int untabify_input = FALSE;
406 /* (-e) The input tab character. */
407 static char input_tab_char = '\t';
409 /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
410 where the leftmost column is 1. */
411 static int chars_per_input_tab = 8;
413 /* (-i) True means convert spaces to tabs on output. */
414 static int tabify_output = FALSE;
416 /* (-i) The output tab character. */
417 static char output_tab_char = '\t';
419 /* (-i) The width of the output tab. */
420 static int chars_per_output_tab = 8;
422 /* Keeps track of pending white space. When we hit a nonspace
423 character after some whitespace, we print whitespace, tabbing
424 if necessary to get to output_position + spaces_not_printed. */
425 static int spaces_not_printed;
427 /* (-o) Number of spaces in the left margin (tabs used when possible). */
428 static int chars_per_margin = 0;
430 /* Position where the next character will fall.
431 Leftmost position is 0 + chars_per_margin.
432 Rightmost position is chars_per_margin + chars_per_line - 1.
433 This is important for converting spaces to tabs on output. */
434 static int output_position;
436 /* Horizontal position relative to the current file.
437 (output_position depends on where we are on the page;
438 input_position depends on where we are in the file.)
439 Important for converting tabs to spaces on input. */
440 static int input_position;
442 /* Count number of failed opens so we can exit with nonzero
443 status if there were any. */
444 static int failed_opens = 0;
446 /* The number of spaces taken up if we print a tab character with width
447 c_ from position h_. */
448 #define TAB_WIDTH(c_, h_) ((c_) - ((h_) % (c_)))
450 /* The horizontal position we'll be at after printing a tab character
451 of width c_ from the position h_. */
452 #define POS_AFTER_TAB(c_, h_) ((h_) + TAB_WIDTH (c_, h_))
454 /* (-NNN) Number of columns of text to print. */
455 static int columns = 1;
457 /* (+NNN:MMM) Page numbers on which to begin and stop printing. */
458 static int first_page_number = 1;
459 static int last_page_number = 0;
461 /* Number of files open (not closed, not on hold). */
462 static int files_ready_to_read = 0;
464 /* Current page number. Displayed in header. */
465 static int page_number;
467 /* Current line number. Displayed when -n flag is specified.
469 When printing files in parallel (-m flag), line numbering is as follows:
470 1 foo goo moo
471 2 hoo too zoo
473 When printing files across (-a flag), ...
474 1 foo 2 moo 3 goo
475 4 hoo 3 too 6 zoo
477 Otherwise, line numbering is as follows:
478 1 foo 3 goo 5 too
479 2 moo 4 hoo 6 zoo */
480 static int line_number;
482 /* (-n) True means lines should be preceded by numbers. */
483 static int numbered_lines = FALSE;
485 /* (-n) Character which follows each line number. */
486 static char number_separator = '\t';
488 /* (-n) line counting starts with 1st line of input file (not with 1st
489 line of 1st page printed). */
490 static int line_count = 1;
492 /* (-n) True means counting of skipped lines starts with 1st line of
493 input file. False means -N option is used in addition, counting of
494 skipped lines not required. */
495 static int skip_count = TRUE;
497 /* (-N) Counting starts with start_line_number = NUMBER at 1st line of
498 first page printed, usually not 1st page of input file. */
499 static int start_line_num = 1;
501 /* (-n) Width in characters of a line number. */
502 static int chars_per_number = 5;
504 /* Used when widening the first column to accommodate numbers -- only
505 needed when printing files in parallel. Includes width of both the
506 number and the number_separator. */
507 static int number_width;
509 /* Buffer sprintf uses to format a line number. */
510 static char *number_buff;
512 /* (-v) True means unprintable characters are printed as escape sequences.
513 control-g becomes \007. */
514 static int use_esc_sequence = FALSE;
516 /* (-c) True means unprintable characters are printed as control prefixes.
517 control-g becomes ^G. */
518 static int use_cntrl_prefix = FALSE;
520 /* (-d) True means output is double spaced. */
521 static int double_space = FALSE;
523 /* Number of files opened initially in init_files. Should be 1
524 unless we're printing multiple files in parallel. */
525 static int total_files = 0;
527 /* (-r) True means don't complain if we can't open a file. */
528 static int ignore_failed_opens = FALSE;
530 /* (-s) True means we separate columns with a specified string.
531 -s option does not affect line truncation nor column alignment. */
532 static int use_col_separator = FALSE;
534 /* String used to separate columns if the -s option has been specified.
535 Default without -s but together with one of the column options
536 -a|COLUMN|-m is a `space' and with the -j option a `tab'. */
537 static char *col_sep_string;
538 static int col_sep_length = 0;
539 static char *column_separator = " ";
540 static char *line_separator = "\t";
542 /* Number of separator characters waiting to be printed as soon as we
543 know that we have any input remaining to be printed. */
544 static int separators_not_printed;
546 /* Position we need to pad to, as soon as we know that we have input
547 remaining to be printed. */
548 static int padding_not_printed;
550 /* True means we should pad the end of the page. Remains false until we
551 know we have a page to print. */
552 static int pad_vertically;
554 /* (-h) String of characters used in place of the filename in the header. */
555 static char *custom_header;
557 /* String containing the date, filename or custom header, and "Page ". */
558 static char *header;
560 static int *clump_buff;
562 /* If nonzero, display usage information and exit. */
563 static int show_help;
565 /* If nonzero, print the version on standard output then exit. */
566 static int show_version;
568 /* True means we read the line no. lines_per_body in skip_read
569 called by skip_to_page. That variable controls the coincidence of a
570 "FF set by hand" and "full_page_printed", see above the definition of
571 structure COLUMN. */
572 static int last_line = FALSE;
574 /* If nonzero, print a non-variable date and time with the header
575 -h HEADER using pr test-suite */
576 static int test_suite;
578 static struct option const long_options[] =
580 {"help", no_argument, &show_help, 1},
581 {"version", no_argument, &show_version, 1},
582 {"test", no_argument, &test_suite, 1},
583 {0, 0, 0, 0}
586 /* Return the number of columns that have either an open file or
587 stored lines. */
589 static int
590 cols_ready_to_print (void)
592 COLUMN *q;
593 int i;
594 int n;
596 n = 0;
597 for (q = column_vector, i = 0; i < columns; ++q, ++i)
598 if (q->status == OPEN ||
599 q->status == FF_FOUND || /* With -b: To print a header only */
600 (storing_columns && q->lines_stored > 0 && q->lines_to_print > 0))
601 ++n;
602 return n;
605 /* Estimate first_ / last_page_number
606 using option +FIRST_PAGE:LAST_PAGE */
608 static void
609 first_last_page (char *pages)
611 char *str1;
613 if (*pages == ':')
615 error (0, 0, _("invalid range of page numbers: `%s'"), pages);
616 usage (2);
619 str1 = strchr (pages, ':');
620 if (str1 != NULL)
621 *str1 = '\0';
624 long int tmp_long;
625 if (xstrtol (pages, NULL, 10, &tmp_long, "") != LONGINT_OK
626 || tmp_long <= 0 || tmp_long > INT_MAX)
627 error (EXIT_FAILURE, 0, _("invalid starting page number: `%s'"),
628 pages);
629 first_page_number = (int) tmp_long;
632 if (str1 == NULL)
633 return;
636 long int tmp_long;
637 if (xstrtol (str1 + 1, NULL, 10, &tmp_long, "") != LONGINT_OK
638 || tmp_long <= 0 || tmp_long > INT_MAX)
639 error (EXIT_FAILURE, 0, _("invalid ending page number: `%s'"),
640 str1 + 1);
641 last_page_number = (int) tmp_long;
644 if (first_page_number > last_page_number)
645 error (EXIT_FAILURE, 0,
646 _("starting page number is larger than ending page number"));
649 /* Estimate length of col_sep_string with option -s[STRING] */
651 static void
652 separator_string (const char *optarg_S)
654 col_sep_length = (int) strlen (optarg_S);
655 col_sep_string = (char *) xmalloc (col_sep_length + 1);
656 strcpy (col_sep_string, optarg_S);
660 main (int argc, char **argv)
662 int c;
663 int accum = 0;
664 int n_files;
665 char **file_names;
667 program_name = argv[0];
668 setlocale (LC_ALL, "");
669 bindtextdomain (PACKAGE, LOCALEDIR);
670 textdomain (PACKAGE);
672 n_files = 0;
673 file_names = (argc > 1
674 ? (char **) xmalloc ((argc - 1) * sizeof (char *))
675 : NULL);
677 while (1)
679 c = getopt_long (argc, argv,
680 "-0123456789abcde::fFh:i::jl:mn::N:o:rs::tTvw:",
681 long_options, NULL);
682 if (c == 1) /* Non-option argument. */
684 char *s;
685 s = optarg;
686 if (*s == '+')
688 ++s;
689 first_last_page (s);
691 else
693 file_names[n_files++] = optarg;
696 else
698 if (ISDIGIT (c))
700 accum = accum * 10 + c - '0';
701 continue;
703 else
705 if (accum > 0)
707 columns = accum;
708 explicit_columns = TRUE;
709 accum = 0;
714 if (c == 1)
715 continue;
717 if (c == EOF)
718 break;
720 switch (c)
722 case 0: /* getopt long option */
723 break;
725 case 'a':
726 print_across_flag = TRUE;
727 storing_columns = FALSE;
728 break;
729 case 'b':
730 balance_columns = TRUE;
731 break;
732 case 'c':
733 use_cntrl_prefix = TRUE;
734 break;
735 case 'd':
736 double_space = TRUE;
737 break;
738 case 'e':
739 if (optarg)
740 getoptarg (optarg, 'e', &input_tab_char,
741 &chars_per_input_tab);
742 /* Could check tab width > 0. */
743 untabify_input = TRUE;
744 break;
745 case 'f':
746 case 'F':
747 use_form_feed = TRUE;
748 break;
749 case 'h':
750 custom_header = optarg;
751 standard_header = FALSE;
752 break;
753 case 'i':
754 if (optarg)
755 getoptarg (optarg, 'i', &output_tab_char,
756 &chars_per_output_tab);
757 /* Could check tab width > 0. */
758 tabify_output = TRUE;
759 break;
760 case 'j':
761 join_lines = TRUE;
762 break;
763 case 'l':
765 long int tmp_long;
766 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
767 || tmp_long <= 0 || tmp_long > INT_MAX)
769 error (EXIT_FAILURE, 0,
770 _("`-l PAGE_LENGTH' invalid number of lines: `%s'"),
771 optarg);
773 lines_per_page = (int) tmp_long;
774 break;
776 case 'm':
777 parallel_files = TRUE;
778 storing_columns = FALSE;
779 break;
780 case 'n':
781 numbered_lines = TRUE;
782 if (optarg)
783 getoptarg (optarg, 'n', &number_separator,
784 &chars_per_number);
785 break;
786 case 'N':
787 skip_count = FALSE;
789 long int tmp_long;
790 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
791 || tmp_long > INT_MAX)
793 error (EXIT_FAILURE, 0,
794 _("`-N NUMBER' invalid starting line number: `%s'"),
795 optarg);
797 start_line_num = (int) tmp_long;
798 break;
800 case 'o':
802 long int tmp_long;
803 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
804 || tmp_long < 0 || tmp_long > INT_MAX)
805 error (EXIT_FAILURE, 0,
806 _("`-o MARGIN' invalid line offset: `%s'"), optarg);
807 chars_per_margin = (int) tmp_long;
808 break;
810 case 'r':
811 ignore_failed_opens = TRUE;
812 break;
813 case 's':
814 use_col_separator = TRUE;
815 if (optarg)
816 separator_string (optarg);
817 break;
818 case 't':
819 extremities = FALSE;
820 keep_FF = TRUE;
821 break;
822 case 'T':
823 extremities = FALSE;
824 keep_FF = FALSE;
825 break;
826 case 'v':
827 use_esc_sequence = TRUE;
828 break;
829 case 'w':
830 truncate_lines = TRUE;
832 long int tmp_long;
833 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
834 || tmp_long <= 0 || tmp_long > INT_MAX)
835 error (EXIT_FAILURE, 0,
836 _("`-w PAGE_WIDTH' invalid column number: `%s'"), optarg);
837 chars_per_line = (int) tmp_long;
838 break;
840 default:
841 usage (2);
842 break;
846 if (show_version)
848 printf ("pr (%s) %s\n", GNU_PACKAGE, VERSION);
849 exit (EXIT_SUCCESS);
852 if (show_help)
853 usage (0);
855 if (parallel_files && explicit_columns)
856 error (EXIT_FAILURE, 0,
857 _("Cannot specify number of columns when printing in parallel."));
859 if (parallel_files && print_across_flag)
860 error (EXIT_FAILURE, 0,
861 _("Cannot specify both printing across and printing in parallel."));
863 for (; optind < argc; optind++)
865 file_names[n_files++] = argv[optind];
868 if (n_files == 0)
870 /* No file arguments specified; read from standard input. */
871 print_files (0, NULL);
873 else
875 if (parallel_files)
876 print_files (n_files, file_names);
877 else
879 int i;
880 for (i = 0; i < n_files; i++)
881 print_files (1, &file_names[i]);
885 cleanup ();
887 if (have_read_stdin && fclose (stdin) == EOF)
888 error (EXIT_FAILURE, errno, _("standard input"));
889 if (ferror (stdout) || fclose (stdout) == EOF)
890 error (EXIT_FAILURE, errno, _("write error"));
891 if (failed_opens > 0)
892 exit (EXIT_FAILURE);
893 exit (EXIT_SUCCESS);
896 /* Parse options of the form -scNNN.
898 Example: -nck, where 'n' is the option, c is the optional number
899 separator, and k is the optional width of the field used when printing
900 a number. */
902 static void
903 getoptarg (char *arg, char switch_char, char *character, int *number)
905 if (!ISDIGIT (*arg))
906 *character = *arg++;
907 if (*arg)
909 long int tmp_long;
910 if (xstrtol (arg, NULL, 10, &tmp_long, "") != LONGINT_OK
911 || tmp_long <= 0 || tmp_long > INT_MAX)
913 error (0, 0,
914 _("`-%c' extra characters or invalid number in the argument: `%s'"),
915 switch_char, arg);
916 usage (2);
918 *number = (int) tmp_long;
922 /* Set parameters related to formatting. */
924 static void
925 init_parameters (int number_of_files)
927 int chars_used_by_number = 0;
929 if (use_form_feed)
931 lines_per_header = 3;
932 lines_per_footer = 0;
935 lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
936 if (lines_per_body <= 0)
938 extremities = FALSE;
939 keep_FF = TRUE;
941 if (extremities == FALSE)
942 lines_per_body = lines_per_page;
944 if (double_space)
945 lines_per_body = lines_per_body / 2;
947 /* If input is stdin, cannot print parallel files. BSD dumps core
948 on this. */
949 if (number_of_files == 0)
950 parallel_files = FALSE;
952 if (parallel_files)
953 columns = number_of_files;
955 /* One file, multi columns down: -b option is set to get a consistent
956 formulation with "FF set by hand" in input files. */
957 if (storing_columns)
958 balance_columns = TRUE;
960 /* Tabification is assumed for multiple columns. */
961 if (columns > 1)
963 if (!use_col_separator)
965 /* Use default separator */
966 if (join_lines)
967 col_sep_string = line_separator;
968 else
969 col_sep_string = column_separator;
970 col_sep_length = 1;
971 use_col_separator = TRUE;
974 truncate_lines = TRUE;
975 untabify_input = TRUE;
976 tabify_output = TRUE;
978 else
979 storing_columns = FALSE;
981 /* -j dominates -w in any case */
982 if (join_lines)
983 truncate_lines = FALSE;
985 if (numbered_lines)
987 line_count = start_line_num;
988 if (number_separator == input_tab_char)
990 number_width = chars_per_number +
991 TAB_WIDTH (chars_per_input_tab,
992 (chars_per_margin + chars_per_number));
994 else
995 number_width = chars_per_number + 1;
996 /* The number is part of the column width unless we are
997 printing files in parallel. */
998 if (parallel_files)
999 chars_used_by_number = number_width;
1002 chars_per_column = (chars_per_line - chars_used_by_number -
1003 (columns - 1) * col_sep_length) / columns;
1005 if (chars_per_column < 1)
1006 error (EXIT_FAILURE, 0, _("page width too narrow"));
1008 if (numbered_lines)
1010 if (number_buff != NULL)
1011 free (number_buff);
1012 number_buff = (char *) xmalloc (2 * chars_per_number);
1015 /* Pick the maximum between the tab width and the width of an
1016 escape sequence. */
1017 if (clump_buff != NULL)
1018 free (clump_buff);
1019 clump_buff = (int *) xmalloc ((chars_per_input_tab > 4
1020 ? chars_per_input_tab : 4) * sizeof (int));
1023 /* Open the necessary files,
1024 maintaining a COLUMN structure for each column.
1026 With multiple files, each column p has a different p->fp.
1027 With single files, each column p has the same p->fp.
1028 Return 1 if (number_of_files > 0) and no files can be opened,
1029 0 otherwise.
1031 With each column/file p, p->full_page_printed is initialized,
1032 see also open_file. */
1034 static int
1035 init_fps (int number_of_files, char **av)
1037 int i, files_left;
1038 COLUMN *p;
1039 FILE *firstfp;
1040 char *firstname;
1042 total_files = 0;
1044 if (column_vector != NULLCOL)
1045 free ((char *) column_vector);
1046 column_vector = (COLUMN *) xmalloc (columns * sizeof (COLUMN));
1048 if (parallel_files)
1050 files_left = number_of_files;
1051 for (p = column_vector; files_left--; ++p, ++av)
1053 if (open_file (*av, p) == 0)
1055 --p;
1056 --columns;
1059 if (columns == 0)
1060 return 1;
1061 init_header ("", -1);
1063 else
1065 p = column_vector;
1066 if (number_of_files > 0)
1068 if (open_file (*av, p) == 0)
1069 return 1;
1070 init_header (*av, fileno (p->fp));
1071 p->lines_stored = 0;
1073 else
1075 p->name = _("standard input");
1076 p->fp = stdin;
1077 have_read_stdin = TRUE;
1078 p->status = OPEN;
1079 p->full_page_printed = FALSE;
1080 ++total_files;
1081 init_header ("", -1);
1082 p->lines_stored = 0;
1085 firstname = p->name;
1086 firstfp = p->fp;
1087 for (i = columns - 1, ++p; i; --i, ++p)
1089 p->name = firstname;
1090 p->fp = firstfp;
1091 p->status = OPEN;
1092 p->full_page_printed = FALSE;
1093 p->lines_stored = 0;
1096 files_ready_to_read = total_files;
1097 return 0;
1100 /* Determine print_func and char_func, the functions
1101 used by each column for printing and/or storing.
1103 Determine the horizontal position desired when we begin
1104 printing a column (p->start_position). */
1106 static void
1107 init_funcs (void)
1109 int i, h, h_next;
1110 COLUMN *p;
1112 h = chars_per_margin;
1114 if (!truncate_lines)
1115 h_next = ANYWHERE;
1116 else
1118 /* When numbering lines of parallel files, we enlarge the
1119 first column to accomodate the number. Looks better than
1120 the Sys V approach. */
1121 if (parallel_files && numbered_lines)
1122 h_next = h + chars_per_column + number_width;
1123 else
1124 h_next = h + chars_per_column;
1127 /* Enlarge p->start_position of first column to use the same form of
1128 padding_not_printed with all columns. */
1129 h = h + col_sep_length;
1131 /* This loop takes care of all but the rightmost column. */
1133 for (p = column_vector, i = 1; i < columns; ++p, ++i)
1135 if (storing_columns) /* One file, multi columns down. */
1137 p->char_func = store_char;
1138 p->print_func = print_stored;
1140 else
1141 /* One file, multi columns across; or parallel files. */
1143 p->char_func = print_char;
1144 p->print_func = read_line;
1147 /* Number only the first column when printing files in
1148 parallel. */
1149 p->numbered = numbered_lines && (!parallel_files || i == 1);
1150 p->start_position = h;
1152 /* If we don't truncate lines, all start_positions are
1153 ANYWHERE, except the first column's start_position when
1154 using a margin. */
1156 if (!truncate_lines)
1158 h = ANYWHERE;
1159 h_next = ANYWHERE;
1161 else
1163 h = h_next + col_sep_length;
1164 h_next = h + chars_per_column;
1168 /* The rightmost column.
1170 Doesn't need to be stored unless we intend to balance
1171 columns on the last page. */
1172 if (storing_columns && balance_columns)
1174 p->char_func = store_char;
1175 p->print_func = print_stored;
1177 else
1179 p->char_func = print_char;
1180 p->print_func = read_line;
1183 p->numbered = numbered_lines && (!parallel_files || i == 1);
1184 p->start_position = h;
1187 /* Open a file. Return nonzero if successful, zero if failed.
1189 With each file p, p->full_page_printed is initialized,
1190 see also init_fps. */
1192 static int
1193 open_file (char *name, COLUMN *p)
1195 if (!strcmp (name, "-"))
1197 p->name = _("standard input");
1198 p->fp = stdin;
1199 have_read_stdin = 1;
1201 else
1203 p->name = name;
1204 p->fp = fopen (name, "r");
1206 if (p->fp == NULL)
1208 ++failed_opens;
1209 if (!ignore_failed_opens)
1210 error (0, errno, "%s", name);
1211 return 0;
1213 p->status = OPEN;
1214 p->full_page_printed = FALSE;
1215 ++total_files;
1216 return 1;
1219 /* Close the file in P.
1221 If we aren't dealing with multiple files in parallel, we change
1222 the status of all columns in the column list to reflect the close. */
1224 static void
1225 close_file (COLUMN *p)
1227 COLUMN *q;
1228 int i;
1230 if (p->status == CLOSED)
1231 return;
1232 if (ferror (p->fp))
1233 error (EXIT_FAILURE, errno, "%s", p->name);
1234 if (p->fp != stdin && fclose (p->fp) == EOF)
1235 error (EXIT_FAILURE, errno, "%s", p->name);
1237 if (!parallel_files)
1239 for (q = column_vector, i = columns; i; ++q, --i)
1241 q->status = CLOSED;
1242 if (q->lines_stored == 0)
1244 q->lines_to_print = 0;
1248 else
1250 p->status = CLOSED;
1251 p->lines_to_print = 0;
1254 --files_ready_to_read;
1257 /* Put a file on hold until we start a new page,
1258 since we've hit a form feed.
1260 If we aren't dealing with parallel files, we must change the
1261 status of all columns in the column list. */
1263 static void
1264 hold_file (COLUMN *p)
1266 COLUMN *q;
1267 int i;
1269 if (!parallel_files)
1270 for (q = column_vector, i = columns; i; ++q, --i)
1272 if (storing_columns)
1273 q->status = FF_FOUND;
1274 else
1275 q->status = ON_HOLD;
1277 else
1278 p->status = ON_HOLD;
1280 p->lines_to_print = 0;
1281 --files_ready_to_read;
1284 /* Undo hold_file -- go through the column list and change any
1285 ON_HOLD columns to OPEN. Used at the end of each page. */
1287 static void
1288 reset_status (void)
1290 int i = columns;
1291 COLUMN *p;
1293 for (p = column_vector; i; --i, ++p)
1294 if (p->status == ON_HOLD)
1296 p->status = OPEN;
1297 files_ready_to_read++;
1300 if (storing_columns)
1301 files_ready_to_read = 1;
1304 /* Print a single file, or multiple files in parallel.
1306 Set up the list of columns, opening the necessary files.
1307 Allocate space for storing columns, if necessary.
1308 Skip to first_page_number, if user has asked to skip leading pages.
1309 Determine which functions are appropriate to store/print lines
1310 in each column.
1311 Print the file(s). */
1313 static void
1314 print_files (int number_of_files, char **av)
1316 init_parameters (number_of_files);
1317 if (init_fps (number_of_files, av))
1318 return;
1319 if (storing_columns)
1320 init_store_cols ();
1322 if (first_page_number > 1)
1324 if (!skip_to_page (first_page_number))
1325 return;
1326 else
1327 page_number = first_page_number;
1329 else
1330 page_number = 1;
1332 init_funcs ();
1334 line_number = line_count;
1335 while (print_page ())
1339 /* Estimate the number of characters taken up by a short format date and
1340 time: "yy-mm-dd HH:MM" and: "Page NNNN". */
1341 #define CHARS_FOR_DATE_AND_PAGE 23
1343 /* Initialize header information.
1344 If DESC is non-negative, it is a file descriptor open to
1345 FILENAME for reading.
1347 Allocate space for a header string,
1348 Determine the time, insert file name or user-specified string.
1349 Make use of a centered header with left-hand-side truncation marked by
1350 a '*` in front, if necessary. */
1352 static void
1353 init_header (char *filename, int desc)
1355 int chars_per_middle, chars_free, lhs_blanks, rhs_blanks;
1356 char *f = filename;
1357 char *no_middle = "";
1358 char *header_text;
1359 struct tm *tmptr;
1360 struct stat st;
1361 char *datim = "- Date/Time --";
1363 if (filename == NULL)
1364 f = "";
1366 if (header != NULL)
1367 free (header);
1368 header = (char *) xmalloc (chars_per_line + 1);
1370 if (!standard_header && *custom_header == '\0')
1371 sprintf (header, "%s", " "); /* blank line header */
1372 else
1374 #define T_BUF_FMT "%Y-%m-%d %H:%M" /* date/time short format */
1375 #define T_BUF_SIZE 17 /* FIXME: using a literal here is fragile. */
1376 char t_buf[T_BUF_SIZE];
1378 /* If parallel files or standard input, use current time. */
1379 if (desc < 0 || !strcmp (filename, "-") || fstat (desc, &st))
1380 st.st_mtime = time (NULL);
1382 tmptr = localtime (&st.st_mtime);
1383 strftime (t_buf, T_BUF_SIZE, T_BUF_FMT, tmptr);
1385 chars_per_middle = chars_per_line - CHARS_FOR_DATE_AND_PAGE;
1386 if (chars_per_middle < 3)
1388 header_text = no_middle; /* Nothing free for a heading */
1389 lhs_blanks = 1;
1390 rhs_blanks = 1;
1392 else
1394 header_text = standard_header ? f : custom_header;
1395 chars_free = chars_per_middle - (int) strlen (header_text);
1396 if (chars_free > 1)
1398 lhs_blanks = chars_free / 2; /* text not truncated */
1399 rhs_blanks = chars_free - lhs_blanks;
1401 else
1402 { /* lhs truncation */
1403 header_text = header_text - chars_free + 2;
1404 *header_text = '*';
1405 lhs_blanks = 1;
1406 rhs_blanks = 1;
1410 sprintf (header, _("%s%*s%s%*sPage"), (test_suite ? datim : t_buf),
1411 lhs_blanks, " ", header_text, rhs_blanks, " ");
1415 /* Set things up for printing a page
1417 Scan through the columns ...
1418 Determine which are ready to print
1419 (i.e., which have lines stored or open files)
1420 Set p->lines_to_print appropriately
1421 (to p->lines_stored if we're storing, or lines_per_body
1422 if we're reading straight from the file)
1423 Keep track of this total so we know when to stop printing */
1425 static void
1426 init_page (void)
1428 int j;
1429 COLUMN *p;
1431 if (storing_columns)
1433 store_columns ();
1434 for (j = columns - 1, p = column_vector; j; --j, ++p)
1436 p->lines_to_print = p->lines_stored;
1439 /* Last column. */
1440 if (balance_columns)
1442 p->lines_to_print = p->lines_stored;
1444 /* Since we're not balancing columns, we don't need to store
1445 the rightmost column. Read it straight from the file. */
1446 else
1448 if (p->status == OPEN)
1450 p->lines_to_print = lines_per_body;
1452 else
1453 p->lines_to_print = 0;
1456 else
1457 for (j = columns, p = column_vector; j; --j, ++p)
1458 if (p->status == OPEN)
1460 p->lines_to_print = lines_per_body;
1462 else
1463 p->lines_to_print = 0;
1466 /* Align empty columns and print separators.
1467 Empty columns will be formed by files with status ON_HOLD or CLOSED
1468 when printing multiple files in parallel. */
1470 static void
1471 align_column (COLUMN *p)
1473 padding_not_printed = p->start_position;
1474 if (padding_not_printed - col_sep_length > 0)
1476 pad_across_to (padding_not_printed - col_sep_length);
1477 padding_not_printed = ANYWHERE;
1480 if (use_col_separator)
1481 print_sep_string ();
1483 if (p->numbered)
1484 add_line_number (p);
1487 /* Print one page.
1489 As long as there are lines left on the page and columns ready to print,
1490 Scan across the column list
1491 if the column has stored lines or the file is open
1492 pad to the appropriate spot
1493 print the column
1494 pad the remainder of the page with \n or \f as requested
1495 reset the status of all files -- any files which where on hold because
1496 of formfeeds are now put back into the lineup. */
1498 static int
1499 print_page (void)
1501 int j;
1502 int lines_left_on_page;
1503 COLUMN *p;
1505 /* Used as an accumulator (with | operator) of successive values of
1506 pad_vertically. The trick is to set pad_vertically
1507 to zero before each run through the inner loop, then after that
1508 loop, it tells us whether a line was actually printed (whether a
1509 newline needs to be output -- or two for double spacing). But those
1510 values have to be accumulated (in pv) so we can invoke pad_down
1511 properly after the outer loop completes. */
1512 int pv;
1514 init_page ();
1516 if (cols_ready_to_print () == 0)
1517 return FALSE;
1519 if (extremities)
1520 print_a_header = TRUE;
1522 /* Don't pad unless we know a page was printed. */
1523 pad_vertically = FALSE;
1524 pv = FALSE;
1526 lines_left_on_page = lines_per_body;
1527 if (double_space)
1528 lines_left_on_page *= 2;
1530 while (lines_left_on_page > 0 && cols_ready_to_print () > 0)
1532 output_position = 0;
1533 spaces_not_printed = 0;
1534 separators_not_printed = 0;
1535 pad_vertically = FALSE;
1536 align_empty_cols = FALSE;
1537 empty_line = TRUE;
1539 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1541 input_position = 0;
1542 if (p->lines_to_print > 0 || p->status == FF_FOUND)
1544 FF_only = FALSE;
1545 padding_not_printed = p->start_position;
1546 if (!(p->print_func) (p))
1547 read_rest_of_line (p);
1548 pv |= pad_vertically;
1550 --p->lines_to_print;
1551 if (p->lines_to_print <= 0)
1553 if (cols_ready_to_print () <= 0)
1554 break;
1557 /* File p changed its status to ON_HOLD or CLOSED */
1558 if (parallel_files && p->status != OPEN)
1560 if (empty_line)
1561 align_empty_cols = TRUE;
1562 else if (p->status == CLOSED ||
1563 (p->status == ON_HOLD && FF_only))
1564 align_column (p);
1567 else if (parallel_files)
1569 /* File status ON_HOLD or CLOSED */
1570 if (empty_line)
1571 align_empty_cols = TRUE;
1572 else
1573 align_column (p);
1576 /* We need it also with an empty column */
1577 if (use_col_separator)
1578 ++separators_not_printed;
1581 if (pad_vertically)
1583 putchar ('\n');
1584 --lines_left_on_page;
1587 if (double_space && pv && extremities)
1589 putchar ('\n');
1590 --lines_left_on_page;
1594 if (lines_left_on_page == 0)
1595 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1596 if (p->status == OPEN)
1597 p->full_page_printed = TRUE;
1599 pad_vertically = pv;
1601 if (pad_vertically && extremities)
1602 pad_down (lines_left_on_page + lines_per_footer);
1603 else if (keep_FF && print_a_FF)
1605 putchar ('\f');
1606 print_a_FF = FALSE;
1609 if (last_page_number && page_number > last_page_number)
1610 return FALSE; /* Stop printing with LAST_PAGE */
1612 reset_status (); /* Change ON_HOLD to OPEN. */
1614 return TRUE; /* More pages to go. */
1617 /* Allocate space for storing columns.
1619 This is necessary when printing multiple columns from a single file.
1620 Lines are stored consecutively in buff, separated by '\0'.
1622 The following doesn't apply any longer - any tuning possible?
1623 (We can't use a fixed offset since with the '-s' flag lines aren't
1624 truncated.)
1626 We maintain a list (line_vector) of pointers to the beginnings
1627 of lines in buff. We allocate one more than the number of lines
1628 because the last entry tells us the index of the last character,
1629 which we need to know in order to print the last line in buff. */
1631 static void
1632 init_store_cols (void)
1634 int total_lines = lines_per_body * columns;
1635 int chars_if_truncate = total_lines * (chars_per_column + 1);
1637 if (line_vector != NULL)
1638 free ((int *) line_vector);
1639 /* FIXME: here's where it was allocated. */
1640 line_vector = (int *) xmalloc ((total_lines + 1) * sizeof (int *));
1642 if (end_vector != NULL)
1643 free ((int *) end_vector);
1644 end_vector = (int *) xmalloc (total_lines * sizeof (int *));
1646 if (buff != NULL)
1647 free (buff);
1648 buff_allocated = (use_col_separator
1649 ? 2 * chars_if_truncate
1650 : chars_if_truncate); /* Tune this. */
1651 buff = (char *) xmalloc (buff_allocated);
1654 /* Store all but the rightmost column.
1655 (Used when printing a single file in multiple downward columns)
1657 For each column
1658 set p->current_line to be the index in line_vector of the
1659 first line in the column
1660 For each line in the column
1661 store the line in buff
1662 add to line_vector the index of the line's first char
1663 buff_start is the index in buff of the first character in the
1664 current line. */
1666 static void
1667 store_columns (void)
1669 int i, j;
1670 int line = 0;
1671 int buff_start;
1672 int last_col; /* The rightmost column which will be saved in buff */
1673 COLUMN *p;
1675 buff_current = 0;
1676 buff_start = 0;
1678 if (balance_columns)
1679 last_col = columns;
1680 else
1681 last_col = columns - 1;
1683 for (i = 1, p = column_vector; i <= last_col; ++i, ++p)
1684 p->lines_stored = 0;
1686 for (i = 1, p = column_vector; i <= last_col && files_ready_to_read;
1687 ++i, ++p)
1689 p->current_line = line;
1690 for (j = lines_per_body; j && files_ready_to_read; --j)
1692 if (p->status == OPEN) /* Redundant. Clean up. */
1694 input_position = 0;
1696 if (!read_line (p))
1697 read_rest_of_line (p);
1699 if (p->status == OPEN
1700 || buff_start != buff_current)
1702 ++p->lines_stored;
1703 line_vector[line] = buff_start;
1704 end_vector[line++] = input_position;
1705 buff_start = buff_current;
1710 /* Keep track of the location of the last char in buff. */
1711 line_vector[line] = buff_start;
1713 if (balance_columns && p->lines_stored != lines_per_body)
1714 balance (line);
1717 static void
1718 balance (int total_stored)
1720 COLUMN *p;
1721 int i, lines;
1722 int first_line = 0;
1724 for (i = 1, p = column_vector; i <= columns; ++i, ++p)
1726 lines = total_stored / columns;
1727 if (i <= total_stored % columns)
1728 ++lines;
1730 p->lines_stored = lines;
1731 p->current_line = first_line;
1733 first_line += lines;
1737 /* Store a character in the buffer. */
1739 static void
1740 store_char (int c)
1742 if (buff_current >= buff_allocated)
1744 /* May be too generous. */
1745 buff_allocated = 2 * buff_allocated;
1746 buff = (char *) xrealloc (buff, buff_allocated * sizeof (char));
1748 buff[buff_current++] = (char) c;
1751 static void
1752 add_line_number (COLUMN *p)
1754 int i;
1755 char *s;
1757 sprintf (number_buff, "%*d", chars_per_number, line_number++);
1758 s = number_buff;
1759 for (i = chars_per_number; i > 0; i--)
1760 (p->char_func) ((int) *s++);
1762 if (number_separator == input_tab_char)
1764 i = number_width - chars_per_number;
1765 while (i-- > 0)
1766 (p->char_func) ((int) ' ');
1768 else
1769 (p->char_func) ((int) number_separator);
1771 if (truncate_lines && !parallel_files)
1772 input_position += number_width;
1775 /* Print (or store) padding until the current horizontal position
1776 is position. */
1778 static void
1779 pad_across_to (int position)
1781 register int h = output_position;
1783 if (tabify_output)
1784 spaces_not_printed = position - output_position;
1785 else
1787 while (++h <= position)
1788 putchar (' ');
1789 output_position = position;
1793 /* Pad to the bottom of the page.
1795 If the user has requested a formfeed, use one.
1796 Otherwise, use newlines. */
1798 static void
1799 pad_down (int lines)
1801 register int i;
1803 if (use_form_feed)
1804 putchar ('\f');
1805 else
1806 for (i = lines; i; --i)
1807 putchar ('\n');
1810 /* Read the rest of the line.
1812 Read from the current column's file until an end of line is
1813 hit. Used when we've truncated a line and we no longer need
1814 to print or store its characters. */
1816 static void
1817 read_rest_of_line (COLUMN *p)
1819 register int c;
1820 FILE *f = p->fp;
1822 while ((c = getc (f)) != '\n')
1824 if (c == '\f')
1826 if ((c = getc (f)) != '\n')
1827 ungetc (c, f);
1828 if (keep_FF)
1829 print_a_FF = TRUE;
1830 hold_file (p);
1831 break;
1833 else if (c == EOF)
1835 close_file (p);
1836 break;
1841 /* Read a line with skip_to_page.
1843 Read from the current column's file until an end of line is
1844 hit. Used when we read full lines to skip pages.
1845 With skip_to_page we have to check for FF-coincidence which is done
1846 in function read_line otherwise.
1847 Count lines of skipped pages to find the line number of 1st page
1848 printed relative to 1st line of input file (start_line_num). */
1850 static void
1851 skip_read (COLUMN *p, int column_number)
1853 register int c;
1854 FILE *f = p->fp;
1855 int i, single_ff = FALSE;
1856 COLUMN *q;
1858 /* Read 1st character in a line or any character succeeding a FF */
1859 if ((c = getc (f)) == '\f' && p->full_page_printed)
1860 /* A FF-coincidence with a previous full_page_printed.
1861 To avoid an additional empty page, eliminate the FF */
1862 if ((c = getc (f)) == '\n')
1863 c = getc (f);
1865 p->full_page_printed = FALSE;
1867 /* 1st character a FF means a single FF without any printable
1868 characters. Don't count it as a line with -n option. */
1869 if (c == '\f')
1870 single_ff = TRUE;
1872 /* Preparing for a FF-coincidence: Maybe we finish that page
1873 without a FF found */
1874 if (last_line)
1875 p->full_page_printed = TRUE;
1877 while (c != '\n')
1879 if (c == '\f')
1881 /* No FF-coincidence possible,
1882 no catching up of a FF-coincidence with next page */
1883 if (last_line)
1885 if (!parallel_files)
1886 for (q = column_vector, i = columns; i; ++q, --i)
1887 q->full_page_printed = FALSE;
1888 else
1889 p->full_page_printed = FALSE;
1892 if ((c = getc (f)) != '\n')
1893 ungetc (c, f);
1894 hold_file (p);
1895 break;
1897 else if (c == EOF)
1899 close_file (p);
1900 break;
1902 c = getc (f);
1905 if (skip_count)
1906 if ((!parallel_files || column_number == 1) && !single_ff)
1907 ++line_count;
1910 /* If we're tabifying output,
1912 When print_char encounters white space it keeps track
1913 of our desired horizontal position and delays printing
1914 until this function is called. */
1916 static void
1917 print_white_space (void)
1919 register int h_new;
1920 register int h_old = output_position;
1921 register int goal = h_old + spaces_not_printed;
1923 while (goal - h_old > 1
1924 && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal)
1926 putchar (output_tab_char);
1927 h_old = h_new;
1929 while (++h_old <= goal)
1930 putchar (' ');
1932 output_position = goal;
1933 spaces_not_printed = 0;
1936 /* Print column separators.
1938 We keep a count until we know that we'll be printing a line,
1939 then print_sep_string() is called. */
1941 static void
1942 print_sep_string ()
1944 char *s;
1945 int l = col_sep_length;
1947 s = col_sep_string;
1949 if (spaces_not_printed > 0)
1950 print_white_space ();
1952 for (; separators_not_printed > 0; --separators_not_printed)
1954 while (l-- > 0)
1955 putchar (*s++);
1956 output_position += col_sep_length;
1960 /* Print (or store, depending on p->char_func) a clump of N
1961 characters. */
1963 static void
1964 print_clump (COLUMN *p, int n, int *clump)
1966 while (n--)
1967 (p->char_func) (*clump++);
1970 /* Print a character.
1972 Update the following comment: process-char hasn't been used any
1973 longer.
1974 If we're tabifying, all tabs have been converted to spaces by
1975 process_char(). Keep a count of consecutive spaces, and when
1976 a nonspace is encountered, call print_white_space() to print the
1977 required number of tabs and spaces. */
1979 static void
1980 print_char (int c)
1982 if (tabify_output)
1984 if (c == ' ')
1986 ++spaces_not_printed;
1987 return;
1989 else if (spaces_not_printed > 0)
1990 print_white_space ();
1992 /* Nonprintables are assumed to have width 0, except '\b'. */
1993 if (!ISPRINT (c))
1995 if (c == '\b')
1996 --output_position;
1998 else
1999 ++output_position;
2001 putchar (c);
2004 /* Skip to page PAGE before printing. */
2006 static int
2007 skip_to_page (int page)
2009 int n, i, j;
2010 COLUMN *p;
2012 for (n = 1; n < page; ++n)
2014 for (i = 1; i < lines_per_body; ++i)
2016 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2017 if (p->status == OPEN)
2018 skip_read (p, j);
2020 last_line = TRUE;
2021 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2022 if (p->status == OPEN)
2023 skip_read (p, j);
2025 if (storing_columns) /* change FF_FOUND to ON_HOLD */
2026 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2027 p->status = ON_HOLD;
2029 reset_status ();
2030 last_line = FALSE;
2032 return files_ready_to_read > 0;
2035 /* Print a header.
2037 Formfeeds are assumed to use up two lines at the beginning of
2038 the page. */
2040 static void
2041 print_header (void)
2043 if (!use_form_feed)
2044 fprintf (stdout, "\n\n");
2046 output_position = 0;
2047 pad_across_to (chars_per_margin);
2048 print_white_space ();
2050 if (!standard_header && *custom_header == '\0')
2051 fprintf (stdout, "%s\n\n\n", header);
2052 else
2053 fprintf (stdout, "%s%5d\n\n\n", header, page_number++);
2055 print_a_header = FALSE;
2056 output_position = 0;
2059 /* Print (or store, if p->char_func is store_char()) a line.
2061 Read a character to determine whether we have a line or not.
2062 (We may hit EOF, \n, or \f)
2064 Once we know we have a line,
2065 set pad_vertically = TRUE, meaning it's safe
2066 to pad down at the end of the page, since we do have a page.
2067 print a header if needed.
2068 pad across to padding_not_printed if needed.
2069 print any separators which need to be printed.
2070 print a line number if it needs to be printed.
2072 Print the clump which corresponds to the first character.
2074 Enter a loop and keep printing until an end of line condition
2075 exists, or until we exceed chars_per_column.
2077 Return FALSE if we exceed chars_per_column before reading
2078 an end of line character, TRUE otherwise. */
2080 static int
2081 read_line (COLUMN *p)
2083 register int c, chars;
2084 int last_input_position;
2085 int j, k;
2086 COLUMN *q;
2088 /* Suppress `used before initialized' warning. */
2089 #ifdef lint
2090 chars = 0;
2091 #endif
2093 /* read 1st character in each line or any character succeeding a FF: */
2094 c = getc (p->fp);
2096 last_input_position = input_position;
2098 if (c == '\f' && p->full_page_printed)
2099 if ((c = getc (p->fp)) == '\n')
2100 c = getc (p->fp);
2101 p->full_page_printed = FALSE;
2103 switch (c)
2105 case '\f':
2106 if ((c = getc (p->fp)) != '\n')
2107 ungetc (c, p->fp);
2108 FF_only = TRUE;
2109 if (print_a_header && !storing_columns)
2111 pad_vertically = TRUE;
2112 print_header ();
2114 else if (keep_FF)
2115 print_a_FF = TRUE;
2116 hold_file (p);
2117 return TRUE;
2118 case EOF:
2119 close_file (p);
2120 return TRUE;
2121 case '\n':
2122 break;
2123 default:
2124 chars = char_to_clump (c);
2127 if (truncate_lines && input_position > chars_per_column)
2129 input_position = last_input_position;
2130 return FALSE;
2133 if (p->char_func != store_char)
2135 pad_vertically = TRUE;
2137 if (print_a_header && !storing_columns)
2138 print_header ();
2140 if (parallel_files && align_empty_cols)
2142 /* We have to align empty columns at the beginning of a line. */
2143 k = separators_not_printed;
2144 separators_not_printed = 0;
2145 for (j = 1, q = column_vector; j <= k; ++j, ++q)
2147 align_column (q);
2148 separators_not_printed += 1;
2150 padding_not_printed = p->start_position;
2151 if (truncate_lines)
2152 spaces_not_printed = chars_per_column;
2153 else
2154 spaces_not_printed = 0;
2155 align_empty_cols = FALSE;
2158 if (padding_not_printed - col_sep_length > 0)
2160 pad_across_to (padding_not_printed - col_sep_length);
2161 padding_not_printed = ANYWHERE;
2164 if (use_col_separator)
2165 print_sep_string ();
2168 if (p->numbered)
2169 add_line_number (p);
2171 empty_line = FALSE;
2172 if (c == '\n')
2173 return TRUE;
2175 print_clump (p, chars, clump_buff);
2177 for (;;)
2179 c = getc (p->fp);
2181 switch (c)
2183 case '\n':
2184 return TRUE;
2185 case '\f':
2186 if ((c = getc (p->fp)) != '\n')
2187 ungetc (c, p->fp);
2188 if (keep_FF)
2189 print_a_FF = TRUE;
2190 hold_file (p);
2191 return TRUE;
2192 case EOF:
2193 close_file (p);
2194 return TRUE;
2197 last_input_position = input_position;
2198 chars = char_to_clump (c);
2199 if (truncate_lines && input_position > chars_per_column)
2201 input_position = last_input_position;
2202 return FALSE;
2205 print_clump (p, chars, clump_buff);
2209 /* Print a line from buff.
2211 If this function has been called, we know we have "something to
2212 print". But it remains to be seen whether we have a real text page
2213 or an empty page (a single form feed) with/without a header only.
2214 Therefore first we set pad_vertically to TRUE and print a header
2215 if necessary.
2216 If FF_FOUND and we are using -t|-T option we omit any newline by
2217 setting pad_vertically to FALSE (see print_page).
2218 Otherwise we pad across if necessary, print separators if necessary
2219 and text of COLUMN *p.
2221 Return TRUE, meaning there is no need to call read_rest_of_line. */
2223 static int
2224 print_stored (COLUMN *p)
2226 COLUMN *q;
2227 int i;
2229 int line = p->current_line++;
2230 register char *first = &buff[line_vector[line]];
2231 /* FIXME
2232 UMR: Uninitialized memory read:
2233 * This is occurring while in:
2234 print_stored [pr.c:2239]
2235 * Reading 4 bytes from 0x5148c in the heap.
2236 * Address 0x5148c is 4 bytes into a malloc'd block at 0x51488 of 676 bytes
2237 * This block was allocated from:
2238 malloc [rtlib.o]
2239 xmalloc [xmalloc.c:94]
2240 init_store_cols [pr.c:1648]
2242 register char *last = &buff[line_vector[line + 1]];
2244 pad_vertically = TRUE;
2246 if (print_a_header)
2247 print_header ();
2249 if (p->status == FF_FOUND)
2251 for (i = 1, q = column_vector; i <= columns; ++i, ++q)
2252 q->status = ON_HOLD;
2253 if (column_vector->lines_to_print <= 0)
2255 if (!extremities)
2256 pad_vertically = FALSE;
2257 return TRUE; /* print a header only */
2261 if (padding_not_printed - col_sep_length > 0)
2263 pad_across_to (padding_not_printed - col_sep_length);
2264 padding_not_printed = ANYWHERE;
2267 if (use_col_separator)
2268 print_sep_string ();
2270 while (first != last)
2271 print_char (*first++);
2273 if (spaces_not_printed == 0)
2275 output_position = p->start_position + end_vector[line];
2276 if (p->start_position - col_sep_length == chars_per_margin)
2277 output_position -= col_sep_length;
2280 return TRUE;
2283 /* Convert a character to the proper format and return the number of
2284 characters in the resulting clump. Increment input_position by
2285 the width of the clump.
2287 Tabs are converted to clumps of spaces.
2288 Nonprintable characters may be converted to clumps of escape
2289 sequences or control prefixes.
2291 Note: the width of a clump is not necessarily equal to the number of
2292 characters in clump_buff. (e.g, the width of '\b' is -1, while the
2293 number of characters is 1.) */
2295 static int
2296 char_to_clump (int c)
2298 register int *s = clump_buff;
2299 register int i;
2300 char esc_buff[4];
2301 int width;
2302 int chars;
2304 if (c == input_tab_char)
2306 width = TAB_WIDTH (chars_per_input_tab, input_position);
2308 if (untabify_input)
2310 for (i = width; i; --i)
2311 *s++ = ' ';
2312 chars = width;
2314 else
2316 *s = c;
2317 chars = 1;
2321 else if (!ISPRINT (c))
2323 if (use_esc_sequence)
2325 width = 4;
2326 chars = 4;
2327 *s++ = '\\';
2328 sprintf (esc_buff, "%03o", c);
2329 for (i = 0; i <= 2; ++i)
2330 *s++ = (int) esc_buff[i];
2332 else if (use_cntrl_prefix)
2334 if (c < 0200)
2336 width = 2;
2337 chars = 2;
2338 *s++ = '^';
2339 *s++ = c ^ 0100;
2341 else
2343 width = 4;
2344 chars = 4;
2345 *s++ = '\\';
2346 sprintf (esc_buff, "%03o", c);
2347 for (i = 0; i <= 2; ++i)
2348 *s++ = (int) esc_buff[i];
2351 else if (c == '\b')
2353 width = -1;
2354 chars = 1;
2355 *s = c;
2357 else
2359 width = 0;
2360 chars = 1;
2361 *s = c;
2364 else
2366 width = 1;
2367 chars = 1;
2368 *s = c;
2371 input_position += width;
2372 return chars;
2375 /* We've just printed some files and need to clean up things before
2376 looking for more options and printing the next batch of files.
2378 Free everything we've xmalloc'ed, except `header'. */
2380 static void
2381 cleanup (void)
2383 if (number_buff)
2384 free (number_buff);
2385 if (clump_buff)
2386 free (clump_buff);
2387 if (column_vector)
2388 free (column_vector);
2389 if (line_vector)
2390 free (line_vector);
2391 if (end_vector)
2392 free (end_vector);
2393 if (buff)
2394 free (buff);
2397 /* Complain, print a usage message, and die. */
2399 static void
2400 usage (int status)
2402 if (status != 0)
2403 fprintf (stderr, _("Try `%s --help' for more information.\n"),
2404 program_name);
2405 else
2407 printf (_("\
2408 Usage: %s [OPTION]... [FILE]...\n\
2410 program_name);
2412 printf (_("\
2413 Paginate or columnate FILE(s) for printing.\n\
2415 +FIRST_PAGE[:LAST_PAGE]\n\
2416 begin [stop] printing with page FIRST_[LAST_]PAGE\n\
2417 -COLUMN produce COLUMN-column output and print columns down,\n\
2418 unless -a is used. Balance number of lines in the\n\
2419 columns on each page.\n\
2420 -a print columns across rather than down, used together\n\
2421 with -COLUMN\n\
2422 -c use hat notation (^G) and octal backslash notation\n\
2423 -d double space the output\n\
2424 -e[CHAR[WIDTH]] expand input CHARs (TABs) to tab WIDTH (8)\n\
2425 -F, -f use form feeds instead of newlines to separate pages\n\
2426 (by a 3-line page header with -f or a 5-line header\n\
2427 and trailer without -f)\n\
2428 -h HEADER use a centered HEADER instead of filename in page headers\n\
2429 with long headers left-hand-side truncation may occur\n\
2430 -h \"\" prints a blank line. Don't use -h\"\"\n\
2431 -i[CHAR[WIDTH]] replace spaces with CHARs (TABs) to tab WIDTH (8)\n\
2432 -j merge full lines, turns off -w line truncation, no column\n\
2433 alignment, -s[STRING] sets separators\n\
2434 -l PAGE_LENGTH set the page length to PAGE_LENGTH (66) lines\n\
2435 (default number of lines of text 56, with -f 63)\n"));
2436 printf (_("\
2437 -m print all files in parallel, one in each column,\n\
2438 truncate lines, but join lines of full length with -j\n\
2439 -n[SEP[DIGITS]] number lines, use DIGITS (5) digits, then SEP (TAB)\n\
2440 default counting starts with 1st line of input file\n\
2441 -N NUMBER start counting with NUMBER at 1st line of first\n\
2442 page printed (see +FIRST_PAGE)\n\
2443 -o MARGIN offset each line with MARGIN spaces (do not affect -w)\n\
2444 -r inhibit warning when a file cannot be opened\n\
2445 -s[STRING] separate columns by an optional STRING, don't use\n\
2446 -s \"STRING\", -s only: No separator used (same as -s\"\"),\n\
2447 without -s: Default separator \'TAB\' with -j and \'space\'\n\
2448 otherwise (same as -s\" \")\n\
2449 -t inhibit page headers and trailers\n\
2450 -T inhibit page headers and trailers, eliminate any page\n\
2451 layout by form feeds set in input files\n\
2452 -v use octal backslash notation\n\
2453 -w PAGE_WIDTH set page width to PAGE_WIDTH (72) columns, truncate\n\
2454 lines (see also -j option)\n\
2455 --help display this help and exit\n\
2456 --version output version information and exit\n\
2458 -T implied by -l nn when nn <= 10 or <= 3 with -f. With no FILE, or when\n\
2459 FILE is -, read standard input.\n\
2460 "));
2461 puts (_("\nReport bugs to <textutils-bugs@gnu.org>."));
2463 exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);