Clone the Makefile.am from join-test.
[coreutils.git] / src / pr.c
blob3ac39ae166248c3467e481c372f33659cc764d7b
1 /* pr -- convert text files for printing.
2 Copyright (C) 1988, 1991, 1995, 1996 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
16 Foundation, 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 'space' s used,
137 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 #if HAVE_LIMITS_H
182 #include <limits.h>
183 #endif
185 char *xmalloc ();
186 char *xrealloc ();
188 #ifndef UINT_MAX
189 #define UINT_MAX ((unsigned int) ~(unsigned int) 0)
190 #endif
192 #ifndef INT_MAX
193 #define INT_MAX ((int) (UINT_MAX >> 1))
194 #endif
196 #ifndef TRUE
197 #define TRUE 1
198 #define FALSE 0
199 #endif
201 /* Used with start_position in the struct COLUMN described below.
202 If start_position == ANYWHERE, we aren't truncating columns and
203 can begin printing a column anywhere. Otherwise we must pad to
204 the horizontal position start_position. */
205 #define ANYWHERE 0
207 /* Each column has one of these structures allocated for it.
208 If we're only dealing with one file, fp is the same for all
209 columns.
211 The general strategy is to spend time setting up these column
212 structures (storing columns if necessary), after which printing
213 is a matter of flitting from column to column and calling
214 print_func.
216 Parallel files, single files printing across in multiple
217 columns, and single files printing down in multiple columns all
218 fit the same printing loop.
220 print_func Function used to print lines in this column.
221 If we're storing this column it will be
222 print_stored(), Otherwise it will be read_line().
224 char_func Function used to process characters in this column.
225 If we're storing this column it will be store_char(),
226 otherwise it will be print_char().
228 current_line Index of the current entry in line_vector, which
229 contains the index of the first character of the
230 current line in buff[].
232 lines_stored Number of lines in this column which are stored in
233 buff.
235 lines_to_print If we're storing this column, lines_to_print is
236 the number of stored_lines which remain to be
237 printed. Otherwise it is the number of lines
238 we can print without exceeding lines_per_body.
240 start_position The horizontal position we want to be in before we
241 print the first character in this column.
243 numbered True means precede this column with a line number. */
245 struct COLUMN
247 FILE *fp; /* Input stream for this column. */
248 char *name; /* File name. */
249 enum
251 OPEN,
252 FF_FOUND, /* used with -b option, set with \f, changed
253 to ON_HOLD after print_header */
254 ON_HOLD, /* Hit a form feed. */
255 CLOSED
257 status; /* Status of the file pointer. */
258 int (*print_func) (); /* Func to print lines in this col. */
259 void (*char_func) (); /* Func to print/store chars in this col. */
260 int current_line; /* Index of current place in line_vector. */
261 int lines_stored; /* Number of lines stored in buff. */
262 int lines_to_print; /* No. lines stored or space left on page. */
263 int start_position; /* Horizontal position of first char. */
264 int numbered;
265 int full_page_printed; /* True means printed without a FF found. */
267 /* p->full_page_printed controls a special case of "FF set by hand":
268 True means a full page has been printed without FF found. To avoid an
269 additional empty page we have to ignore a FF immediately following in
270 the next line. */
273 typedef struct COLUMN COLUMN;
275 #define NULLCOL (COLUMN *)0
277 static int char_to_clump __P ((int c));
278 static int read_line __P ((COLUMN *p));
279 static int print_page __P ((void));
280 static int print_stored __P ((COLUMN *p));
281 static int open_file __P ((char *name, COLUMN *p));
282 static int skip_to_page __P ((int page));
283 static void print_header __P ((void));
284 static void pad_across_to __P ((int position));
285 static void number __P ((COLUMN *p));
286 static void getoptarg __P ((char *arg, char switch_char, char *character, int *number));
287 static void usage __P ((int status));
288 static void print_files __P ((int number_of_files, char **av));
289 static void init_parameters __P ((int number_of_files));
290 static void init_header __P ((char *filename, int desc));
291 static void init_store_cols __P ((void));
292 static void store_columns __P ((void));
293 static void balance __P ((int total_stored));
294 static void store_char __P ((int c));
295 static void pad_down __P ((int lines));
296 static void read_rest_of_line __P ((COLUMN *p));
297 static void skip_read __P ((COLUMN *p, int column_number));
298 static void print_char __P ((int c));
299 static void cleanup __P ((void));
300 static void first_last_page __P ((char *pages));
301 static void print_sep_string __P ((void));
302 static void separator_string __P ((const char *optarg_S));
304 /* The name under which this program was invoked. */
305 char *program_name;
307 /* All of the columns to print. */
308 static COLUMN *column_vector;
310 /* When printing a single file in multiple downward columns,
311 we store the leftmost columns contiguously in buff.
312 To print a line from buff, get the index of the first character
313 from line_vector[i], and print up to line_vector[i + 1]. */
314 static char *buff;
316 /* Index of the position in buff where the next character
317 will be stored. */
318 static int buff_current;
320 /* The number of characters in buff.
321 Used for allocation of buff and to detect overflow of buff. */
322 static int buff_allocated;
324 /* Array of indices into buff.
325 Each entry is an index of the first character of a line.
326 This is used when storing lines to facilitate shuffling when
327 we do column balancing on the last page. */
328 static int *line_vector;
330 /* Array of horizonal positions.
331 For each line in line_vector, end_vector[line] is the horizontal
332 position we are in after printing that line. We keep track of this
333 so that we know how much we need to pad to prepare for the next
334 column. */
335 static int *end_vector;
337 /* (-m) True means we're printing multiple files in parallel. */
338 static int parallel_files = FALSE;
340 /* (-m) True means a line starts with some empty columns (some files
341 already CLOSED or ON_HOLD) which we have to align. */
342 static int align_empty_cols;
344 /* (-m) True means we have not yet found any printable column in a line.
345 align_empty_cols = TRUE has to be maintained. */
346 static int empty_line;
348 /* (-m) False means printable column output precedes a form feed found.
349 Column align is done only once. No additional action with that form
350 feed.
351 True means we found only a form feed in a column. Maybe we have to do
352 some column align with that form feed. */
353 static int FF_only;
355 /* (-[0-9]+) True means we're given an option explicitly specifying
356 number of columns. Used to detect when this option is used with -m. */
357 static int explicit_columns = FALSE;
359 /* (-t|-T) False means we aren't printing headers and footers. */
360 static int extremities = TRUE;
362 /* (-t) True means we retain all FF set by hand in input files.
363 False is set with -T option. */
364 static int keep_FF = FALSE;
365 static int print_a_FF = FALSE;
367 /* True means we need to print a header as soon as we know we've got input
368 to print after it. */
369 static int print_a_header;
371 /* (-h) True means we're using the standard header rather than a
372 customized one specified by the -h flag. */
373 static int standard_header = TRUE;
375 /* (-f) True means use formfeeds instead of newlines to separate pages. */
376 static int use_form_feed = FALSE;
378 /* True means we have read the standard input. */
379 static int have_read_stdin = FALSE;
381 /* True means the -a flag has been given. */
382 static int print_across_flag = FALSE;
384 /* True means we're printing one file in multiple (>1) downward columns. */
385 static int storing_columns = TRUE;
387 /* (-b) True means balance columns on the last page as Sys V does. */
388 /* That's no longer an independent option. With storing_columns = TRUE
389 balance_columns = TRUE is used too (s. function init_parameters).
390 We get a consistent formulation with "FF set by hand" in input files. */
391 static int balance_columns = FALSE;
393 /* (-l) Number of lines on a page, including header and footer lines. */
394 static int lines_per_page = 66;
396 /* Number of lines in the header and footer can be reset to 0 using
397 the -t flag. */
398 static int lines_per_header = 5;
399 static int lines_per_body;
400 static int lines_per_footer = 5;
402 /* (-w) Width in characters of the page. Does not include the width of
403 the margin. */
404 static int chars_per_line = 72;
406 /* (-w) True means we truncate lines longer than chars_per_column. */
407 static int truncate_lines = FALSE;
409 /* (-j) True means we join lines without any line truncation. -j
410 dominates -w option. */
411 static int join_lines = FALSE;
413 /* Number of characters in a column. Based on col_sep_length and
414 page width. */
415 static int chars_per_column;
417 /* (-e) True means convert tabs to spaces on input. */
418 static int untabify_input = FALSE;
420 /* (-e) The input tab character. */
421 static char input_tab_char = '\t';
423 /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
424 where the leftmost column is 1. */
425 static int chars_per_input_tab = 8;
427 /* (-i) True means convert spaces to tabs on output. */
428 static int tabify_output = FALSE;
430 /* (-i) The output tab character. */
431 static char output_tab_char = '\t';
433 /* (-i) The width of the output tab. */
434 static int chars_per_output_tab = 8;
436 /* Keeps track of pending white space. When we hit a nonspace
437 character after some whitespace, we print whitespace, tabbing
438 if necessary to get to output_position + spaces_not_printed. */
439 static int spaces_not_printed;
441 /* (-o) Number of spaces in the left margin (tabs used when possible). */
442 static int chars_per_margin = 0;
444 /* Position where the next character will fall.
445 Leftmost position is 0 + chars_per_margin.
446 Rightmost position is chars_per_margin + chars_per_line - 1.
447 This is important for converting spaces to tabs on output. */
448 static int output_position;
450 /* Horizontal position relative to the current file.
451 (output_position depends on where we are on the page;
452 input_position depends on where we are in the file.)
453 Important for converting tabs to spaces on input. */
454 static int input_position;
456 /* Count number of failed opens so we can exit with nonzero
457 status if there were any. */
458 static int failed_opens = 0;
460 /* The horizontal position we'll be at after printing a tab character
461 of width c_ from the position h_. */
462 #define pos_after_tab(c_, h_) h_ - h_ % c_ + c_
464 /* The number of spaces taken up if we print a tab character with width
465 c_ from position h_. */
466 #define tab_width(c_, h_) - h_ % c_ + c_
468 /* (-NNN) Number of columns of text to print. */
469 static int columns = 1;
471 /* (+NNN:MMM) Page numbers on which to begin and stop printing. */
472 static int first_page_number = 1;
473 static int last_page_number = 0;
475 /* Number of files open (not closed, not on hold). */
476 static int files_ready_to_read = 0;
478 /* Current page number. Displayed in header. */
479 static int page_number;
481 /* Current line number. Displayed when -n flag is specified.
483 When printing files in parallel (-m flag), line numbering is as follows:
484 1 foo goo moo
485 2 hoo too zoo
487 When printing files across (-a flag), ...
488 1 foo 2 moo 3 goo
489 4 hoo 3 too 6 zoo
491 Otherwise, line numbering is as follows:
492 1 foo 3 goo 5 too
493 2 moo 4 hoo 6 zoo */
494 static int line_number;
496 /* (-n) True means lines should be preceded by numbers. */
497 static int numbered_lines = FALSE;
499 /* (-n) Character which follows each line number. */
500 static char number_separator = '\t';
502 /* (-n) line counting starts with 1st line of input file (not with 1st
503 line of 1st page printed). */
504 static int line_count = 1;
506 /* (-n) True means counting of skipped lines starts with 1st line of
507 input file. False means -N option is used in addition, counting of
508 skipped lines not required. */
509 static int skip_count = TRUE;
511 /* (-N) Counting starts with start_line_number = NUMBER at 1st line of
512 first page printed, usually not 1st page of input file. */
513 static int start_line_num = 1;
515 /* (-n) Width in characters of a line number. */
516 static int chars_per_number = 5;
518 /* Used when widening the first column to accommodate numbers -- only
519 needed when printing files in parallel. Includes width of both the
520 number and the number_separator. */
521 static int number_width;
523 /* Buffer sprintf uses to format a line number. */
524 static char *number_buff;
526 /* (-v) True means unprintable characters are printed as escape sequences.
527 control-g becomes \007. */
528 static int use_esc_sequence = FALSE;
530 /* (-c) True means unprintable characters are printed as control prefixes.
531 control-g becomes ^G. */
532 static int use_cntrl_prefix = FALSE;
534 /* (-d) True means output is double spaced. */
535 static int double_space = FALSE;
537 /* Number of files opened initially in init_files. Should be 1
538 unless we're printing multiple files in parallel. */
539 static int total_files = 0;
541 /* (-r) True means don't complain if we can't open a file. */
542 static int ignore_failed_opens = FALSE;
544 /* (-s) True means we separate columns with a specified string.
545 -s option does not affect line truncation nor column alignment. */
546 static int use_col_separator = FALSE;
548 /* String used to separate columns if the -s option has been specified.
549 Default value with -s is a space. */
550 static char *col_sep_string;
551 static int col_sep_length = 0;
552 static char *column_separator = " ";
554 /* Number of separator characters waiting to be printed as soon as we
555 know that we have any input remaining to be printed. */
556 static int separators_not_printed;
558 /* Position we need to pad to, as soon as we know that we have input
559 remaining to be printed. */
560 static int padding_not_printed;
562 /* True means we should pad the end of the page. Remains false until we
563 know we have a page to print. */
564 static int pad_vertically;
566 /* (-h) String of characters used in place of the filename in the header. */
567 static char *custom_header;
569 /* String containing the date, filename or custom header, and "Page ". */
570 static char *header;
572 static int *clump_buff;
574 /* If nonzero, display usage information and exit. */
575 static int show_help;
577 /* If nonzero, print the version on standard output then exit. */
578 static int show_version;
580 /* True means we read the line no. lines_per_body in skip_read
581 called by skip_to_page. That variable controls the coincidence of a
582 "FF set by hand" and "full_page_printed", see above the definition of
583 structure COLUMN. */
584 static int last_line = FALSE;
586 /* If nonzero, print a non-variable date and time with the header
587 -h HEADER using pr test-suite */
588 static int test_suite;
590 static struct option const long_options[] =
592 {"help", no_argument, &show_help, 1},
593 {"version", no_argument, &show_version, 1},
594 {"test", no_argument, &test_suite, 1},
595 {0, 0, 0, 0}
598 /* Return the number of columns that have either an open file or
599 stored lines. */
601 static int
602 cols_ready_to_print (void)
604 COLUMN *q;
605 int i;
606 int n;
608 n = 0;
609 for (q = column_vector, i = 0; i < columns; ++q, ++i)
610 if (q->status == OPEN ||
611 q->status == FF_FOUND || /* With -b: To print a header only */
612 (storing_columns && q->lines_stored > 0 && q->lines_to_print > 0))
613 ++n;
614 return n;
617 /* Estimate first_ / last_page_number
618 using option +FIRST_PAGE:LAST_PAGE */
620 static void
621 first_last_page (char *pages)
623 char *str1;
625 if (*pages == ':')
627 error (0, 0, _("invalid range of page numbers: `%s'"), pages);
628 usage (2);
631 str1 = strchr (pages, ':');
632 if (str1 != NULL)
633 *str1 = '\0';
636 long int tmp_long;
637 if (xstrtol (pages, NULL, 10, &tmp_long, NULL) != LONGINT_OK
638 || tmp_long <= 0 || tmp_long > INT_MAX)
639 error (EXIT_FAILURE, 0, _("invalid starting page number: `%s'"),
640 pages);
641 first_page_number = (int) tmp_long;
644 if (str1 == NULL)
645 return;
648 long int tmp_long;
649 if (xstrtol (str1 + 1, NULL, 10, &tmp_long, NULL) != LONGINT_OK
650 || tmp_long <= 0 || tmp_long > INT_MAX)
651 error (EXIT_FAILURE, 0, _("invalid ending page number: `%s'"),
652 str1 + 1);
653 last_page_number = (int) tmp_long;
656 if (first_page_number > last_page_number)
657 error (EXIT_FAILURE, 0,
658 _("starting page number is larger than ending page number"));
661 /* Estimate length of col_sep_string with option -s[STRING] */
663 static void
664 separator_string (const char *optarg_S)
666 col_sep_length = (int) strlen (optarg_S);
667 col_sep_string = (char *) xmalloc (col_sep_length + 1);
668 strcpy (col_sep_string, optarg_S);
672 main (int argc, char **argv)
674 int c;
675 int accum = 0;
676 int n_files;
677 char **file_names;
679 program_name = argv[0];
680 setlocale (LC_ALL, "");
681 bindtextdomain (PACKAGE, LOCALEDIR);
682 textdomain (PACKAGE);
684 n_files = 0;
685 file_names = (argc > 1
686 ? (char **) xmalloc ((argc - 1) * sizeof (char *))
687 : NULL);
689 while (1)
691 c = getopt_long (argc, argv,
692 "-0123456789abcde::fFh:i::jl:mn::N:o:rs::tTvw:",
693 long_options, NULL);
694 if (c == 1) /* Non-option argument. */
696 char *s;
697 s = optarg;
698 if (*s == '+')
700 ++s;
701 first_last_page (s);
703 else
705 file_names[n_files++] = optarg;
708 else
710 if (ISDIGIT (c))
712 accum = accum * 10 + c - '0';
713 continue;
715 else
717 if (accum > 0)
719 columns = accum;
720 explicit_columns = TRUE;
721 accum = 0;
726 if (c == 1)
727 continue;
729 if (c == EOF)
730 break;
732 switch (c)
734 case 0: /* getopt long option */
735 break;
737 case 'a':
738 print_across_flag = TRUE;
739 storing_columns = FALSE;
740 break;
741 case 'b':
742 balance_columns = TRUE;
743 break;
744 case 'c':
745 use_cntrl_prefix = TRUE;
746 break;
747 case 'd':
748 double_space = TRUE;
749 break;
750 case 'e':
751 if (optarg)
752 getoptarg (optarg, 'e', &input_tab_char,
753 &chars_per_input_tab);
754 /* Could check tab width > 0. */
755 untabify_input = TRUE;
756 break;
757 case 'f':
758 case 'F':
759 use_form_feed = TRUE;
760 break;
761 case 'h':
762 custom_header = optarg;
763 standard_header = FALSE;
764 break;
765 case 'i':
766 if (optarg)
767 getoptarg (optarg, 'i', &output_tab_char,
768 &chars_per_output_tab);
769 /* Could check tab width > 0. */
770 tabify_output = TRUE;
771 break;
772 case 'j':
773 join_lines = TRUE;
774 break;
775 case 'l':
777 long int tmp_long;
778 if (xstrtol (optarg, NULL, 10, &tmp_long, NULL) != LONGINT_OK
779 || tmp_long <= 0 || tmp_long > INT_MAX)
781 error (EXIT_FAILURE, 0,
782 _("`-l PAGE_LENGTH' invalid number of lines: `%s'"),
783 optarg);
785 lines_per_page = (int) tmp_long;
786 break;
788 case 'm':
789 parallel_files = TRUE;
790 storing_columns = FALSE;
791 break;
792 case 'n':
793 numbered_lines = TRUE;
794 if (optarg)
795 getoptarg (optarg, 'n', &number_separator,
796 &chars_per_number);
797 break;
798 case 'N':
799 skip_count = FALSE;
801 long int tmp_long;
802 if (xstrtol (optarg, NULL, 10, &tmp_long, NULL) != LONGINT_OK
803 || tmp_long > INT_MAX)
805 error (EXIT_FAILURE, 0,
806 _("`-N NUMBER' invalid starting line number: `%s'"),
807 optarg);
809 start_line_num = (int) tmp_long;
810 break;
812 case 'o':
814 long int tmp_long;
815 if (xstrtol (optarg, NULL, 10, &tmp_long, NULL) != LONGINT_OK
816 || tmp_long <= 0 || tmp_long > INT_MAX)
817 error (EXIT_FAILURE, 0,
818 _("`-o MARGIN' invalid line offset: `%s'"), optarg);
819 chars_per_margin = (int) tmp_long;
820 break;
822 case 'r':
823 ignore_failed_opens = TRUE;
824 break;
825 case 's':
826 use_col_separator = TRUE;
827 if (optarg)
828 separator_string (optarg);
829 break;
830 case 't':
831 extremities = FALSE;
832 keep_FF = TRUE;
833 break;
834 case 'T':
835 extremities = FALSE;
836 keep_FF = FALSE;
837 break;
838 case 'v':
839 use_esc_sequence = TRUE;
840 break;
841 case 'w':
842 truncate_lines = TRUE;
844 long int tmp_long;
845 if (xstrtol (optarg, NULL, 10, &tmp_long, NULL) != LONGINT_OK
846 || tmp_long <= 0 || tmp_long > INT_MAX)
847 error (EXIT_FAILURE, 0,
848 _("`-w PAGE_WIDTH' invalid column number: `%s'"), optarg);
849 chars_per_line = (int) tmp_long;
850 break;
852 default:
853 usage (2);
854 break;
858 if (show_version)
860 printf ("pr (%s) %s\n", GNU_PACKAGE, VERSION);
861 exit (EXIT_SUCCESS);
864 if (show_help)
865 usage (0);
867 if (parallel_files && explicit_columns)
868 error (EXIT_FAILURE, 0,
869 _("Cannot specify number of columns when printing in parallel."));
871 if (parallel_files && print_across_flag)
872 error (EXIT_FAILURE, 0,
873 _("Cannot specify both printing across and printing in parallel."));
875 for (; optind < argc; optind++)
877 file_names[n_files++] = argv[optind];
880 if (n_files == 0)
882 /* No file arguments specified; read from standard input. */
883 print_files (0, NULL);
885 else
887 if (parallel_files)
888 print_files (n_files, file_names);
889 else
891 int i;
892 for (i = 0; i < n_files; i++)
893 print_files (1, &file_names[i]);
897 cleanup ();
899 if (have_read_stdin && fclose (stdin) == EOF)
900 error (EXIT_FAILURE, errno, _("standard input"));
901 if (ferror (stdout) || fclose (stdout) == EOF)
902 error (EXIT_FAILURE, errno, _("write error"));
903 if (failed_opens > 0)
904 exit (EXIT_FAILURE);
905 exit (EXIT_SUCCESS);
908 /* Parse options of the form -scNNN.
910 Example: -nck, where 'n' is the option, c is the optional number
911 separator, and k is the optional width of the field used when printing
912 a number. */
914 static void
915 getoptarg (char *arg, char switch_char, char *character, int *number)
917 if (!ISDIGIT (*arg))
918 *character = *arg++;
919 if (*arg)
921 long int tmp_long;
922 if (xstrtol (arg, NULL, 10, &tmp_long, NULL) != LONGINT_OK
923 || tmp_long <= 0 || tmp_long > INT_MAX)
925 error (0, 0,
926 _("`-%c' extra characters or invalid number in the argument: `%s'"),
927 switch_char, arg);
928 usage (2);
930 *number = (int) tmp_long;
934 /* Set parameters related to formatting. */
936 static void
937 init_parameters (int number_of_files)
939 int chars_used_by_number = 0;
941 if (use_form_feed)
943 lines_per_header = 3;
944 lines_per_footer = 0;
947 lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
948 if (lines_per_body <= 0)
950 extremities = FALSE;
951 keep_FF = TRUE;
953 if (extremities == FALSE)
954 lines_per_body = lines_per_page;
956 if (double_space)
957 lines_per_body = lines_per_body / 2;
959 /* If input is stdin, cannot print parallel files. BSD dumps core
960 on this. */
961 if (number_of_files == 0)
962 parallel_files = FALSE;
964 if (parallel_files)
965 columns = number_of_files;
967 /* One file, multi columns down: -b option is set to get a consistent
968 formulation with "FF set by hand" in input files. */
969 if (storing_columns)
970 balance_columns = TRUE;
972 /* Tabification is assumed for multiple columns. */
973 if (columns > 1)
975 if (!use_col_separator)
977 col_sep_string = column_separator;
978 col_sep_length = 1;
979 use_col_separator = TRUE;
982 truncate_lines = TRUE;
983 untabify_input = TRUE;
984 tabify_output = TRUE;
986 else
987 storing_columns = FALSE;
989 /* -j dominates -w in any case */
990 if (join_lines)
991 truncate_lines = FALSE;
993 if (numbered_lines)
995 line_count = start_line_num;
996 if (number_separator == input_tab_char)
998 number_width = chars_per_number +
999 tab_width (chars_per_input_tab,
1000 (chars_per_margin + chars_per_number));
1002 else
1003 number_width = chars_per_number + 1;
1004 /* The number is part of the column width unless we are
1005 printing files in parallel. */
1006 if (parallel_files)
1007 chars_used_by_number = number_width;
1010 chars_per_column = (chars_per_line - chars_used_by_number -
1011 (columns - 1) * col_sep_length) / columns;
1013 if (chars_per_column < 1)
1014 error (EXIT_FAILURE, 0, _("page width too narrow"));
1016 if (numbered_lines)
1018 if (number_buff != NULL)
1019 free (number_buff);
1020 number_buff = (char *) xmalloc (2 * chars_per_number);
1023 /* Pick the maximum between the tab width and the width of an
1024 escape sequence. */
1025 if (clump_buff != NULL)
1026 free (clump_buff);
1027 clump_buff = (int *) xmalloc ((chars_per_input_tab > 4
1028 ? chars_per_input_tab : 4) * sizeof (int));
1031 /* Open the necessary files,
1032 maintaining a COLUMN structure for each column.
1034 With multiple files, each column p has a different p->fp.
1035 With single files, each column p has the same p->fp.
1036 Return 1 if (number_of_files > 0) and no files can be opened,
1037 0 otherwise.
1039 With each column/file p, p->full_page_printed is initialized,
1040 see also open_file. */
1042 static int
1043 init_fps (int number_of_files, char **av)
1045 int i, files_left;
1046 COLUMN *p;
1047 FILE *firstfp;
1048 char *firstname;
1050 total_files = 0;
1052 if (column_vector != NULLCOL)
1053 free ((char *) column_vector);
1054 column_vector = (COLUMN *) xmalloc (columns * sizeof (COLUMN));
1056 if (parallel_files)
1058 files_left = number_of_files;
1059 for (p = column_vector; files_left--; ++p, ++av)
1061 if (open_file (*av, p) == 0)
1063 --p;
1064 --columns;
1067 if (columns == 0)
1068 return 1;
1069 init_header ("", -1);
1071 else
1073 p = column_vector;
1074 if (number_of_files > 0)
1076 if (open_file (*av, p) == 0)
1077 return 1;
1078 init_header (*av, fileno (p->fp));
1080 else
1082 p->name = _("standard input");
1083 p->fp = stdin;
1084 have_read_stdin = TRUE;
1085 p->status = OPEN;
1086 p->full_page_printed = FALSE;
1087 ++total_files;
1088 init_header ("", -1);
1091 firstname = p->name;
1092 firstfp = p->fp;
1093 for (i = columns - 1, ++p; i; --i, ++p)
1095 p->name = firstname;
1096 p->fp = firstfp;
1097 p->status = OPEN;
1098 p->full_page_printed = FALSE;
1101 files_ready_to_read = total_files;
1102 return 0;
1105 /* Determine print_func and char_func, the functions
1106 used by each column for printing and/or storing.
1108 Determine the horizontal position desired when we begin
1109 printing a column (p->start_position). */
1111 static void
1112 init_funcs (void)
1114 int i, h, h_next;
1115 COLUMN *p;
1117 h = chars_per_margin;
1119 if (!truncate_lines)
1120 h_next = ANYWHERE;
1121 else
1123 /* When numbering lines of parallel files, we enlarge the
1124 first column to accomodate the number. Looks better than
1125 the Sys V approach. */
1126 if (parallel_files && numbered_lines)
1127 h_next = h + chars_per_column + number_width;
1128 else
1129 h_next = h + chars_per_column;
1132 /* Enlarge p->start_position of first column to use the same form of
1133 padding_not_printed with all columns. */
1134 h = h + col_sep_length;
1136 /* This loop takes care of all but the rightmost column. */
1138 for (p = column_vector, i = 1; i < columns; ++p, ++i)
1140 if (storing_columns) /* One file, multi columns down. */
1142 p->char_func = store_char;
1143 p->print_func = print_stored;
1145 else
1146 /* One file, multi columns across; or parallel files. */
1148 p->char_func = print_char;
1149 p->print_func = read_line;
1152 /* Number only the first column when printing files in
1153 parallel. */
1154 p->numbered = numbered_lines && (!parallel_files || i == 1);
1155 p->start_position = h;
1157 /* If we don't truncate lines, all start_positions are
1158 ANYWHERE, except the first column's start_position when
1159 using a margin. */
1161 if (!truncate_lines)
1163 h = ANYWHERE;
1164 h_next = ANYWHERE;
1166 else
1168 h = h_next + col_sep_length;
1169 h_next = h + chars_per_column;
1173 /* The rightmost column.
1175 Doesn't need to be stored unless we intend to balance
1176 columns on the last page. */
1177 if (storing_columns && balance_columns)
1179 p->char_func = store_char;
1180 p->print_func = print_stored;
1182 else
1184 p->char_func = print_char;
1185 p->print_func = read_line;
1188 p->numbered = numbered_lines && (!parallel_files || i == 1);
1189 p->start_position = h;
1192 /* Open a file. Return nonzero if successful, zero if failed.
1194 With each file p, p->full_page_printed is initialized,
1195 see also init_fps. */
1197 static int
1198 open_file (char *name, COLUMN *p)
1200 if (!strcmp (name, "-"))
1202 p->name = _("standard input");
1203 p->fp = stdin;
1204 have_read_stdin = 1;
1206 else
1208 p->name = name;
1209 p->fp = fopen (name, "r");
1211 if (p->fp == NULL)
1213 ++failed_opens;
1214 if (!ignore_failed_opens)
1215 error (0, errno, "%s", name);
1216 return 0;
1218 p->status = OPEN;
1219 p->full_page_printed = FALSE;
1220 ++total_files;
1221 return 1;
1224 /* Close the file in P.
1226 If we aren't dealing with multiple files in parallel, we change
1227 the status of all columns in the column list to reflect the close. */
1229 static void
1230 close_file (COLUMN *p)
1232 COLUMN *q;
1233 int i;
1235 if (p->status == CLOSED)
1236 return;
1237 if (ferror (p->fp))
1238 error (EXIT_FAILURE, errno, "%s", p->name);
1239 if (p->fp != stdin && fclose (p->fp) == EOF)
1240 error (EXIT_FAILURE, errno, "%s", p->name);
1242 if (!parallel_files)
1244 for (q = column_vector, i = columns; i; ++q, --i)
1246 q->status = CLOSED;
1247 if (q->lines_stored == 0)
1249 q->lines_to_print = 0;
1253 else
1255 p->status = CLOSED;
1256 p->lines_to_print = 0;
1259 --files_ready_to_read;
1262 /* Put a file on hold until we start a new page,
1263 since we've hit a form feed.
1265 If we aren't dealing with parallel files, we must change the
1266 status of all columns in the column list. */
1268 static void
1269 hold_file (COLUMN *p)
1271 COLUMN *q;
1272 int i;
1274 if (!parallel_files)
1275 for (q = column_vector, i = columns; i; ++q, --i)
1277 if (storing_columns)
1278 q->status = FF_FOUND;
1279 else
1280 q->status = ON_HOLD;
1282 else
1283 p->status = ON_HOLD;
1285 p->lines_to_print = 0;
1286 --files_ready_to_read;
1289 /* Undo hold_file -- go through the column list and change any
1290 ON_HOLD columns to OPEN. Used at the end of each page. */
1292 static void
1293 reset_status (void)
1295 int i = columns;
1296 COLUMN *p;
1298 for (p = column_vector; i; --i, ++p)
1299 if (p->status == ON_HOLD)
1301 p->status = OPEN;
1302 files_ready_to_read++;
1305 if (storing_columns)
1306 files_ready_to_read = 1;
1309 /* Print a single file, or multiple files in parallel.
1311 Set up the list of columns, opening the necessary files.
1312 Allocate space for storing columns, if necessary.
1313 Skip to first_page_number, if user has asked to skip leading pages.
1314 Determine which functions are appropriate to store/print lines
1315 in each column.
1316 Print the file(s). */
1318 static void
1319 print_files (int number_of_files, char **av)
1321 init_parameters (number_of_files);
1322 if (init_fps (number_of_files, av))
1323 return;
1324 if (storing_columns)
1325 init_store_cols ();
1327 if (first_page_number > 1)
1329 if (!skip_to_page (first_page_number))
1330 return;
1331 else
1332 page_number = first_page_number;
1334 else
1335 page_number = 1;
1337 init_funcs ();
1339 line_number = line_count;
1340 while (print_page ())
1344 /* Estimate the number of characters taken up by a short format date and
1345 time: "yy-mm-dd HH:MM" and: "Page NNNN". */
1346 #define CHARS_FOR_DATE_AND_PAGE 23
1348 /* Initialize header information.
1349 If DESC is non-negative, it is a file descriptor open to
1350 FILENAME for reading.
1352 Allocate space for a header string,
1353 Determine the time, insert file name or user-specified string.
1354 Make use of a centered header with left-hand-side truncation marked by
1355 a '*` in front, if necessary. */
1357 static void
1358 init_header (char *filename, int desc)
1360 int chars_per_middle, chars_free, lhs_blanks, rhs_blanks;
1361 char *f = filename;
1362 char *no_middle = "";
1363 char *header_text, *t_buf;
1364 struct tm *tmptr;
1365 struct stat st;
1366 char *datim = "- Date/Time --";
1368 if (filename == NULL)
1369 f = "";
1371 if (header != NULL)
1372 free (header);
1373 header = (char *) xmalloc (chars_per_line + 1);
1375 if (!standard_header && *custom_header == '\0')
1376 sprintf (header, "%s", " "); /* blank line header */
1377 else
1379 /* If parallel files or standard input, use current time. */
1380 if (desc < 0 || !strcmp (filename, "-") || fstat (desc, &st))
1381 st.st_mtime = time (NULL);
1384 size_t t_buf_size = 15;
1385 const char *fmt = "%y-%m-%d %H:%M"; /* date/time short format */
1387 t_buf = (char *) xmalloc (t_buf_size);
1388 tmptr = localtime (&st.st_mtime);
1389 strftime (t_buf, t_buf_size, fmt, tmptr);
1392 chars_per_middle = chars_per_line - CHARS_FOR_DATE_AND_PAGE;
1393 if (chars_per_middle < 3)
1395 header_text = no_middle; /* Nothing free for a heading */
1396 lhs_blanks = 1;
1397 rhs_blanks = 1;
1399 else
1401 header_text = standard_header ? f : custom_header;
1402 chars_free = chars_per_middle - (int) strlen (header_text);
1403 if (chars_free > 1)
1405 lhs_blanks = chars_free / 2; /* text not truncated */
1406 rhs_blanks = chars_free - lhs_blanks;
1408 else
1409 { /* lhs truncation */
1410 header_text = header_text - chars_free + 2;
1411 *header_text = '*';
1412 lhs_blanks = 1;
1413 rhs_blanks = 1;
1417 sprintf (header, _("%s%*s%s%*sPage"), (test_suite ? datim : t_buf),
1418 lhs_blanks, " ", header_text, rhs_blanks, " ");
1422 /* Set things up for printing a page
1424 Scan through the columns ...
1425 Determine which are ready to print
1426 (i.e., which have lines stored or open files)
1427 Set p->lines_to_print appropriately
1428 (to p->lines_stored if we're storing, or lines_per_body
1429 if we're reading straight from the file)
1430 Keep track of this total so we know when to stop printing */
1432 static void
1433 init_page (void)
1435 int j;
1436 COLUMN *p;
1438 if (storing_columns)
1440 store_columns ();
1441 for (j = columns - 1, p = column_vector; j; --j, ++p)
1443 p->lines_to_print = p->lines_stored;
1446 /* Last column. */
1447 if (balance_columns)
1449 p->lines_to_print = p->lines_stored;
1451 /* Since we're not balancing columns, we don't need to store
1452 the rightmost column. Read it straight from the file. */
1453 else
1455 if (p->status == OPEN)
1457 p->lines_to_print = lines_per_body;
1459 else
1460 p->lines_to_print = 0;
1463 else
1464 for (j = columns, p = column_vector; j; --j, ++p)
1465 if (p->status == OPEN)
1467 p->lines_to_print = lines_per_body;
1469 else
1470 p->lines_to_print = 0;
1473 /* Align empty columns and print separators.
1474 Empty columns will be formed by files with status ON_HOLD or CLOSED
1475 when printing multiple files in parallel. */
1477 static void
1478 align_column (COLUMN *p)
1480 padding_not_printed = p->start_position;
1481 if (padding_not_printed - col_sep_length > 0)
1483 pad_across_to (padding_not_printed - col_sep_length);
1484 padding_not_printed = ANYWHERE;
1487 if (use_col_separator)
1488 print_sep_string ();
1490 if (p->numbered)
1491 number (p);
1494 /* Print one page.
1496 As long as there are lines left on the page and columns ready to print,
1497 Scan across the column list
1498 if the column has stored lines or the file is open
1499 pad to the appropriate spot
1500 print the column
1501 pad the remainder of the page with \n or \f as requested
1502 reset the status of all files -- any files which where on hold because
1503 of formfeeds are now put back into the lineup. */
1505 static int
1506 print_page (void)
1508 int j;
1509 int lines_left_on_page;
1510 COLUMN *p;
1512 /* Used as an accumulator (with | operator) of successive values of
1513 pad_vertically. The trick is to set pad_vertically
1514 to zero before each run through the inner loop, then after that
1515 loop, it tells us whether a line was actually printed (whether a
1516 newline needs to be output -- or two for double spacing). But those
1517 values have to be accumulated (in pv) so we can invoke pad_down
1518 properly after the outer loop completes. */
1519 int pv;
1521 init_page ();
1523 if (cols_ready_to_print () == 0)
1524 return FALSE;
1526 if (extremities)
1527 print_a_header = TRUE;
1529 /* Don't pad unless we know a page was printed. */
1530 pad_vertically = FALSE;
1531 pv = FALSE;
1533 lines_left_on_page = lines_per_body;
1534 if (double_space)
1535 lines_left_on_page *= 2;
1537 while (lines_left_on_page > 0 && cols_ready_to_print () > 0)
1539 output_position = 0;
1540 spaces_not_printed = 0;
1541 separators_not_printed = 0;
1542 pad_vertically = FALSE;
1543 align_empty_cols = FALSE;
1544 empty_line = TRUE;
1546 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1548 input_position = 0;
1549 if (p->lines_to_print > 0 || p->status == FF_FOUND)
1551 FF_only = FALSE;
1552 padding_not_printed = p->start_position;
1553 if (!(p->print_func) (p))
1554 read_rest_of_line (p);
1555 pv |= pad_vertically;
1557 --p->lines_to_print;
1558 if (p->lines_to_print <= 0)
1560 if (cols_ready_to_print () <= 0)
1561 break;
1564 /* File p changed its status to ON_HOLD or CLOSED */
1565 if (parallel_files && p->status != OPEN)
1567 if (empty_line)
1568 align_empty_cols = TRUE;
1569 else if (p->status == CLOSED ||
1570 (p->status == ON_HOLD && FF_only))
1571 align_column (p);
1574 else if (parallel_files)
1576 /* File status ON_HOLD or CLOSED */
1577 if (empty_line)
1578 align_empty_cols = TRUE;
1579 else
1580 align_column (p);
1583 /* We need it also with an empty column */
1584 if (use_col_separator)
1585 ++separators_not_printed;
1588 if (pad_vertically)
1590 putchar ('\n');
1591 --lines_left_on_page;
1594 if (double_space && pv && extremities)
1596 putchar ('\n');
1597 --lines_left_on_page;
1601 if (lines_left_on_page == 0)
1602 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1603 if (p->status == OPEN)
1604 p->full_page_printed = TRUE;
1606 pad_vertically = pv;
1608 if (pad_vertically && extremities)
1609 pad_down (lines_left_on_page + lines_per_footer);
1610 else if (keep_FF && print_a_FF)
1612 putchar ('\f');
1613 print_a_FF = FALSE;
1616 if (last_page_number && page_number > last_page_number)
1617 return FALSE; /* Stop printing with LAST_PAGE */
1619 reset_status (); /* Change ON_HOLD to OPEN. */
1621 return TRUE; /* More pages to go. */
1624 /* Allocate space for storing columns.
1626 This is necessary when printing multiple columns from a single file.
1627 Lines are stored consecutively in buff, separated by '\0'.
1629 The following doesn't apply any longer - any tuning possible?
1630 (We can't use a fixed offset since with the '-s' flag lines aren't
1631 truncated.)
1633 We maintain a list (line_vector) of pointers to the beginnings
1634 of lines in buff. We allocate one more than the number of lines
1635 because the last entry tells us the index of the last character,
1636 which we need to know in order to print the last line in buff. */
1638 static void
1639 init_store_cols (void)
1641 int total_lines = lines_per_body * columns;
1642 int chars_if_truncate = total_lines * (chars_per_column + 1);
1644 if (line_vector != NULL)
1645 free ((int *) line_vector);
1646 line_vector = (int *) xmalloc ((total_lines + 1) * sizeof (int *));
1648 if (end_vector != NULL)
1649 free ((int *) end_vector);
1650 end_vector = (int *) xmalloc (total_lines * sizeof (int *));
1652 if (buff != NULL)
1653 free (buff);
1654 buff_allocated = (use_col_separator
1655 ? 2 * chars_if_truncate
1656 : chars_if_truncate); /* Tune this. */
1657 buff = (char *) xmalloc (buff_allocated);
1660 /* Store all but the rightmost column.
1661 (Used when printing a single file in multiple downward columns)
1663 For each column
1664 set p->current_line to be the index in line_vector of the
1665 first line in the column
1666 For each line in the column
1667 store the line in buff
1668 add to line_vector the index of the line's first char
1669 buff_start is the index in buff of the first character in the
1670 current line. */
1672 static void
1673 store_columns (void)
1675 int i, j;
1676 int line = 0;
1677 int buff_start;
1678 int last_col; /* The rightmost column which will be saved in buff */
1679 COLUMN *p;
1681 buff_current = 0;
1682 buff_start = 0;
1684 if (balance_columns)
1685 last_col = columns;
1686 else
1687 last_col = columns - 1;
1689 for (i = 1, p = column_vector; i <= last_col; ++i, ++p)
1690 p->lines_stored = 0;
1692 for (i = 1, p = column_vector; i <= last_col && files_ready_to_read;
1693 ++i, ++p)
1695 p->current_line = line;
1696 for (j = lines_per_body; j && files_ready_to_read; --j)
1698 if (p->status == OPEN) /* Redundant. Clean up. */
1700 input_position = 0;
1702 if (!read_line (p))
1703 read_rest_of_line (p);
1705 if (p->status == OPEN
1706 || buff_start != buff_current)
1708 ++p->lines_stored;
1709 line_vector[line] = buff_start;
1710 end_vector[line++] = input_position;
1711 buff_start = buff_current;
1716 /* Keep track of the location of the last char in buff. */
1717 line_vector[line] = buff_start;
1719 if (balance_columns && p->lines_stored != lines_per_body)
1720 balance (line);
1723 static void
1724 balance (int total_stored)
1726 COLUMN *p;
1727 int i, lines;
1728 int first_line = 0;
1730 for (i = 1, p = column_vector; i <= columns; ++i, ++p)
1732 lines = total_stored / columns;
1733 if (i <= total_stored % columns)
1734 ++lines;
1736 p->lines_stored = lines;
1737 p->current_line = first_line;
1739 first_line += lines;
1743 /* Store a character in the buffer. */
1745 static void
1746 store_char (int c)
1748 if (buff_current >= buff_allocated)
1750 /* May be too generous. */
1751 buff_allocated = 2 * buff_allocated;
1752 buff = (char *) xrealloc (buff, buff_allocated * sizeof (char));
1754 buff[buff_current++] = (char) c;
1757 static void
1758 number (COLUMN *p)
1760 int i;
1761 char *s;
1763 sprintf (number_buff, "%*d", chars_per_number, line_number++);
1764 s = number_buff;
1765 for (i = chars_per_number; i > 0; i--)
1766 (p->char_func) ((int) *s++);
1768 if (number_separator == input_tab_char)
1770 i = number_width - chars_per_number;
1771 while (i-- > 0)
1772 (p->char_func) ((int) ' ');
1774 else
1775 (p->char_func) ((int) number_separator);
1777 if (truncate_lines && !parallel_files)
1778 input_position += number_width;
1781 /* Print (or store) padding until the current horizontal position
1782 is position. */
1784 static void
1785 pad_across_to (int position)
1787 register int h = output_position;
1789 if (tabify_output)
1790 spaces_not_printed = position - output_position;
1791 else
1793 while (++h <= position)
1794 putchar (' ');
1795 output_position = position;
1799 /* Pad to the bottom of the page.
1801 If the user has requested a formfeed, use one.
1802 Otherwise, use newlines. */
1804 static void
1805 pad_down (int lines)
1807 register int i;
1809 if (use_form_feed)
1810 putchar ('\f');
1811 else
1812 for (i = lines; i; --i)
1813 putchar ('\n');
1816 /* Read the rest of the line.
1818 Read from the current column's file until an end of line is
1819 hit. Used when we've truncated a line and we no longer need
1820 to print or store its characters. */
1822 static void
1823 read_rest_of_line (COLUMN *p)
1825 register int c;
1826 FILE *f = p->fp;
1828 while ((c = getc (f)) != '\n')
1830 if (c == '\f')
1832 if ((c = getc (f)) != '\n')
1833 ungetc (c, f);
1834 if (keep_FF)
1835 print_a_FF = TRUE;
1836 hold_file (p);
1837 break;
1839 else if (c == EOF)
1841 close_file (p);
1842 break;
1847 /* Read a line with skip_to_page.
1849 Read from the current column's file until an end of line is
1850 hit. Used when we read full lines to skip pages.
1851 With skip_to_page we have to check for FF-coincidence which is done
1852 in function read_line otherwise.
1853 Count lines of skipped pages to find the line number of 1st page
1854 printed relative to 1st line of input file (start_line_num). */
1856 static void
1857 skip_read (COLUMN *p, int column_number)
1859 register int c;
1860 FILE *f = p->fp;
1861 int i, single_ff = FALSE;
1862 COLUMN *q;
1864 /* Read 1st character in a line or any character succeeding a FF */
1865 if ((c = getc (f)) == '\f' && p->full_page_printed)
1866 /* A FF-coincidence with a previous full_page_printed.
1867 To avoid an additional empty page, eliminate the FF */
1868 if ((c = getc (f)) == '\n')
1869 c = getc (f);
1871 p->full_page_printed = FALSE;
1873 /* 1st character a FF means a single FF without any printable
1874 characters. Don't count it as a line with -n option. */
1875 if (c == '\f')
1876 single_ff = TRUE;
1878 /* Preparing for a FF-coincidence: Maybe we finish that page
1879 without a FF found */
1880 if (last_line)
1881 p->full_page_printed = TRUE;
1883 while (c != '\n')
1885 if (c == '\f')
1887 /* No FF-coincidence possible,
1888 no catching up of a FF-coincidence with next page */
1889 if (last_line)
1891 if (!parallel_files)
1892 for (q = column_vector, i = columns; i; ++q, --i)
1893 q->full_page_printed = FALSE;
1894 else
1895 p->full_page_printed = FALSE;
1898 if ((c = getc (f)) != '\n')
1899 ungetc (c, f);
1900 hold_file (p);
1901 break;
1903 else if (c == EOF)
1905 close_file (p);
1906 break;
1908 c = getc (f);
1911 if (skip_count)
1912 if ((!parallel_files || column_number == 1) && !single_ff)
1913 ++line_count;
1916 /* If we're tabifying output,
1918 When print_char encounters white space it keeps track
1919 of our desired horizontal position and delays printing
1920 until this function is called. */
1922 static void
1923 print_white_space (void)
1925 register int h_new;
1926 register int h_old = output_position;
1927 register int goal = h_old + spaces_not_printed;
1929 while (goal - h_old > 1
1930 && (h_new = pos_after_tab (chars_per_output_tab, h_old)) <= goal)
1932 putchar (output_tab_char);
1933 h_old = h_new;
1935 while (++h_old <= goal)
1936 putchar (' ');
1938 output_position = goal;
1939 spaces_not_printed = 0;
1942 /* Print column separators.
1944 We keep a count until we know that we'll be printing a line,
1945 then print_sep_string() is called. */
1947 static void
1948 print_sep_string ()
1950 char *s;
1951 int l = col_sep_length;
1953 s = col_sep_string;
1955 if (spaces_not_printed > 0)
1956 print_white_space ();
1958 for (; separators_not_printed > 0; --separators_not_printed)
1960 while (l-- > 0)
1961 putchar (*s++);
1962 output_position += col_sep_length;
1966 /* Print (or store, depending on p->char_func) a clump of N
1967 characters. */
1969 static void
1970 print_clump (COLUMN *p, int n, int *clump)
1972 while (n--)
1973 (p->char_func) (*clump++);
1976 /* Print a character.
1978 Update the following comment: process-char hasn't been used any
1979 longer.
1980 If we're tabifying, all tabs have been converted to spaces by
1981 process_char(). Keep a count of consecutive spaces, and when
1982 a nonspace is encountered, call print_white_space() to print the
1983 required number of tabs and spaces. */
1985 static void
1986 print_char (int c)
1988 if (tabify_output)
1990 if (c == ' ')
1992 ++spaces_not_printed;
1993 return;
1995 else if (spaces_not_printed > 0)
1996 print_white_space ();
1998 /* Nonprintables are assumed to have width 0, except '\b'. */
1999 if (!ISPRINT (c))
2001 if (c == '\b')
2002 --output_position;
2004 else
2005 ++output_position;
2007 putchar (c);
2010 /* Skip to page PAGE before printing. */
2012 static int
2013 skip_to_page (int page)
2015 int n, i, j;
2016 COLUMN *p;
2018 for (n = 1; n < page; ++n)
2020 for (i = 1; i < lines_per_body; ++i)
2022 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2023 if (p->status == OPEN)
2024 skip_read (p, j);
2026 last_line = TRUE;
2027 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2028 if (p->status == OPEN)
2029 skip_read (p, j);
2031 if (storing_columns) /* change FF_FOUND to ON_HOLD */
2032 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2033 p->status = ON_HOLD;
2035 reset_status ();
2036 last_line = FALSE;
2038 return files_ready_to_read > 0;
2041 /* Print a header.
2043 Formfeeds are assumed to use up two lines at the beginning of
2044 the page. */
2046 static void
2047 print_header (void)
2049 if (!use_form_feed)
2050 fprintf (stdout, "\n\n");
2052 output_position = 0;
2053 pad_across_to (chars_per_margin);
2054 print_white_space ();
2056 if (!standard_header && *custom_header == '\0')
2057 fprintf (stdout, "%s\n\n\n", header);
2058 else
2059 fprintf (stdout, "%s%5d\n\n\n", header, page_number++);
2061 print_a_header = FALSE;
2062 output_position = 0;
2065 /* Print (or store, if p->char_func is store_char()) a line.
2067 Read a character to determine whether we have a line or not.
2068 (We may hit EOF, \n, or \f)
2070 Once we know we have a line,
2071 set pad_vertically = TRUE, meaning it's safe
2072 to pad down at the end of the page, since we do have a page.
2073 print a header if needed.
2074 pad across to padding_not_printed if needed.
2075 print any separators which need to be printed.
2076 print a line number if it needs to be printed.
2078 Print the clump which corresponds to the first character.
2080 Enter a loop and keep printing until an end of line condition
2081 exists, or until we exceed chars_per_column.
2083 Return FALSE if we exceed chars_per_column before reading
2084 an end of line character, TRUE otherwise. */
2086 static int
2087 read_line (COLUMN *p)
2089 register int c, chars;
2090 int last_input_position;
2091 int j, k;
2092 COLUMN *q;
2094 /* Suppress `used before initialized' warning. */
2095 #ifdef lint
2096 chars = 0;
2097 #endif
2099 /* read 1st character in each line or any character succeeding a FF: */
2100 c = getc (p->fp);
2102 last_input_position = input_position;
2104 if (c == '\f' && p->full_page_printed)
2105 if ((c = getc (p->fp)) == '\n')
2106 c = getc (p->fp);
2107 p->full_page_printed = FALSE;
2109 switch (c)
2111 case '\f':
2112 if ((c = getc (p->fp)) != '\n')
2113 ungetc (c, p->fp);
2114 FF_only = TRUE;
2115 if (print_a_header && !storing_columns)
2117 pad_vertically = TRUE;
2118 print_header ();
2120 else if (keep_FF)
2121 print_a_FF = TRUE;
2122 hold_file (p);
2123 return TRUE;
2124 case EOF:
2125 close_file (p);
2126 return TRUE;
2127 case '\n':
2128 break;
2129 default:
2130 chars = char_to_clump (c);
2133 if (truncate_lines && input_position > chars_per_column)
2135 input_position = last_input_position;
2136 return FALSE;
2139 if (p->char_func != store_char)
2141 pad_vertically = TRUE;
2143 if (print_a_header && !storing_columns)
2144 print_header ();
2146 if (parallel_files && align_empty_cols)
2148 /* We have to align empty columns at the beginning of a line. */
2149 k = separators_not_printed;
2150 separators_not_printed = 0;
2151 for (j = 1, q = column_vector; j <= k; ++j, ++q)
2153 align_column (q);
2154 separators_not_printed += 1;
2156 padding_not_printed = p->start_position;
2157 if (truncate_lines)
2158 spaces_not_printed = chars_per_column;
2159 else
2160 spaces_not_printed = 0;
2161 align_empty_cols = FALSE;
2164 if (padding_not_printed - col_sep_length > 0)
2166 pad_across_to (padding_not_printed - col_sep_length);
2167 padding_not_printed = ANYWHERE;
2170 if (use_col_separator)
2171 print_sep_string ();
2174 if (p->numbered)
2175 number (p);
2177 empty_line = FALSE;
2178 if (c == '\n')
2179 return TRUE;
2181 print_clump (p, chars, clump_buff);
2183 for (;;)
2185 c = getc (p->fp);
2187 switch (c)
2189 case '\n':
2190 return TRUE;
2191 case '\f':
2192 if ((c = getc (p->fp)) != '\n')
2193 ungetc (c, p->fp);
2194 if (keep_FF)
2195 print_a_FF = TRUE;
2196 hold_file (p);
2197 return TRUE;
2198 case EOF:
2199 close_file (p);
2200 return TRUE;
2203 last_input_position = input_position;
2204 chars = char_to_clump (c);
2205 if (truncate_lines && input_position > chars_per_column)
2207 input_position = last_input_position;
2208 return FALSE;
2211 print_clump (p, chars, clump_buff);
2215 /* Print a line from buff.
2217 If this function has been called, we know we have "something to
2218 print". But it remains to be seen whether we have a real text page
2219 or an empty page (a single form feed) with/without a header only.
2220 Therefore first we set pad_vertically to TRUE and print a header
2221 if necessary.
2222 If FF_FOUND and we are using -t|-T option we omit any newline by
2223 setting pad_vertically to FALSE (see print_page).
2224 Otherwise we pad across if necessary, print separators if necessary
2225 and text of COLUMN *p.
2227 Return TRUE, meaning there is no need to call read_rest_of_line. */
2229 static int
2230 print_stored (COLUMN *p)
2232 COLUMN *q;
2233 int i;
2235 int line = p->current_line++;
2236 register char *first = &buff[line_vector[line]];
2237 register char *last = &buff[line_vector[line + 1]];
2239 pad_vertically = TRUE;
2241 if (print_a_header)
2242 print_header ();
2244 if (p->status == FF_FOUND)
2246 for (i = 1, q = column_vector; i <= columns; ++i, ++q)
2247 q->status = ON_HOLD;
2248 if (column_vector->lines_to_print <= 0)
2250 if (!extremities)
2251 pad_vertically = FALSE;
2252 return TRUE; /* print a header only */
2256 if (padding_not_printed - col_sep_length > 0)
2258 pad_across_to (padding_not_printed - col_sep_length);
2259 padding_not_printed = ANYWHERE;
2262 if (use_col_separator)
2263 print_sep_string ();
2265 while (first != last)
2266 print_char (*first++);
2268 if (spaces_not_printed == 0)
2270 output_position = p->start_position + end_vector[line];
2271 if (p->start_position - col_sep_length == chars_per_margin)
2272 output_position -= col_sep_length;
2275 return TRUE;
2278 /* Convert a character to the proper format and return the number of
2279 characters in the resulting clump. Increment input_position by
2280 the width of the clump.
2282 Tabs are converted to clumps of spaces.
2283 Nonprintable characters may be converted to clumps of escape
2284 sequences or control prefixes.
2286 Note: the width of a clump is not necessarily equal to the number of
2287 characters in clump_buff. (e.g, the width of '\b' is -1, while the
2288 number of characters is 1.) */
2290 static int
2291 char_to_clump (int c)
2293 register int *s = clump_buff;
2294 register int i;
2295 char esc_buff[4];
2296 int width;
2297 int chars;
2299 if (c == input_tab_char)
2301 width = tab_width (chars_per_input_tab, input_position);
2303 if (untabify_input)
2305 for (i = width; i; --i)
2306 *s++ = ' ';
2307 chars = width;
2309 else
2311 *s = c;
2312 chars = 1;
2316 else if (!ISPRINT (c))
2318 if (use_esc_sequence)
2320 width = 4;
2321 chars = 4;
2322 *s++ = '\\';
2323 sprintf (esc_buff, "%03o", c);
2324 for (i = 0; i <= 2; ++i)
2325 *s++ = (int) esc_buff[i];
2327 else if (use_cntrl_prefix)
2329 if (c < 0200)
2331 width = 2;
2332 chars = 2;
2333 *s++ = '^';
2334 *s++ = c ^ 0100;
2336 else
2338 width = 4;
2339 chars = 4;
2340 *s++ = '\\';
2341 sprintf (esc_buff, "%03o", c);
2342 for (i = 0; i <= 2; ++i)
2343 *s++ = (int) esc_buff[i];
2346 else if (c == '\b')
2348 width = -1;
2349 chars = 1;
2350 *s = c;
2352 else
2354 width = 0;
2355 chars = 1;
2356 *s = c;
2359 else
2361 width = 1;
2362 chars = 1;
2363 *s = c;
2366 input_position += width;
2367 return chars;
2370 /* We've just printed some files and need to clean up things before
2371 looking for more options and printing the next batch of files.
2373 Free everything we've xmalloc'ed, except `header'. */
2375 static void
2376 cleanup (void)
2378 if (number_buff)
2379 free (number_buff);
2380 if (clump_buff)
2381 free (clump_buff);
2382 if (column_vector)
2383 free (column_vector);
2384 if (line_vector)
2385 free (line_vector);
2386 if (end_vector)
2387 free (end_vector);
2388 if (buff)
2389 free (buff);
2392 /* Complain, print a usage message, and die. */
2394 static void
2395 usage (int status)
2397 if (status != 0)
2398 fprintf (stderr, _("Try `%s --help' for more information.\n"),
2399 program_name);
2400 else
2402 printf (_("\
2403 Usage: %s [OPTION]... [FILE]...\n\
2405 program_name);
2407 printf (_("\
2408 Paginate or columnate FILE(s) for printing.\n\
2410 +FIRST_PAGE[:LAST_PAGE]\n\
2411 begin [stop] printing with page FIRST_[LAST_]PAGE\n\
2412 -COLUMN produce COLUMN-column output and print columns down,\n\
2413 unless -a is used. Balance number of lines in the\n\
2414 columns on each page.\n\
2415 -a print columns across rather than down, used together\n\
2416 with -COLUMN\n\
2417 -c use hat notation (^G) and octal backslash notation\n\
2418 -d double space the output\n\
2419 -e[CHAR[WIDTH]] expand input CHARs (TABs) to tab WIDTH (8)\n\
2420 -F, -f use form feeds instead of newlines to separate pages\n\
2421 (by a 3-line page header with -f or a 5-line header\n\
2422 and trailer without -f)\n\
2423 -h HEADER use a centered HEADER instead of filename in page headers\n\
2424 with long headers left-hand-side truncation may occur\n\
2425 -h \"\" prints a blank line. Don't use -h\"\"\n\
2426 -i[CHAR[WIDTH]] replace spaces with CHARs (TABs) to tab WIDTH (8)\n\
2427 -j merge full lines, turns off -w line truncation, no column\n\
2428 alignment, -s[STRING] sets separators\n\
2429 -l PAGE_LENGTH set the page length to PAGE_LENGTH (66) lines\n\
2430 (default number of lines of text 56, with -f 63)\n\
2431 -m print all files in parallel, one in each column,\n\
2432 truncate lines, but join lines of full length with -j\n\
2433 -n[SEP[DIGITS]] number lines, use DIGITS (5) digits, then SEP (TAB)\n\
2434 default counting starts with 1st line of input file\n\
2435 -N NUMBER start counting with NUMBER at 1st line of first\n\
2436 page printed (see +FIRST_PAGE)\n\
2437 -o MARGIN offset each line with MARGIN spaces (do not affect -w)\n\
2438 -r inhibit warning when a file cannot be opened\n\
2439 -s[STRING] separate columns by an optional STRING\n\
2440 don't use -s \"STRING\" \n\
2441 without -s: default sep. \'space\' used, same as -s\" \"\n\
2442 -s only: no separator used, same as -s\"\" \n\
2443 -t inhibit page headers and trailers\n\
2444 -T inhibit page headers and trailers, eliminate any page\n\
2445 layout by form feeds set in input files\n\
2446 -v use octal backslash notation\n\
2447 -w PAGE_WIDTH set page width to PAGE_WIDTH (72) columns, truncate\n\
2448 lines (see also -j option)\n\
2449 --help display this help and exit\n\
2450 --version output version information and exit\n\
2452 -T implied by -l nn when nn <= 10 or <= 3 with -f. With no FILE, or when\n\
2453 FILE is -, read standard input.\n\
2454 "));
2455 puts (_("\nReport bugs to textutils-bugs@gnu.ai.mit.edu"));
2457 exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);