1 /* pr -- convert text files for printing.
2 Copyright (C) 1988, 1991, 1995 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
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
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.
35 +PAGE Begin output at page PAGE of the output.
37 -COLUMN Produce output that is COLUMN columns wide and print
40 -a Print columns across rather than down. The input
49 -b Balance columns on the last page.
51 -c Print unprintable characters as control prefixes.
52 Control-g is printed as ^G.
54 -d Double space the output.
56 -e[c[k]] Expand tabs to spaces on input. Optional argument C
57 is the input tab character. (Default is `\t'.) Optional
58 argument K is the input tab character's width. (Default is 8.)
61 -f Use formfeeds instead of newlines to separate pages.
63 -h header Replace the filename in the header with the string HEADER.
65 -i[c[k]] Replace spaces with tabs on output. Optional argument
66 C is the output tab character. (Default is `\t'.) Optional
67 argument K is the output tab character's width. (Default
70 -l lines Set the page length to LINES. Default is 66.
72 -m Print files in parallel.
74 -n[c[k]] Precede each column with a line number.
75 (With parallel files, precede each line with a line
76 number.) Optional argument C is the character to print
77 after each number. (Default `\t'.) Optional argument
78 K is the number of digits per line number. (Default 5.)
80 -o offset Offset each line with a margin OFFSET spaces wide.
81 Total page width is the size of this offset plus the
84 -r Ignore files that can't be opened.
86 -s[c] Separate each line with a character. Optional argument C is
87 the character to be used. Default is `\t'.
89 -t Do not print headers or footers.
91 -v Print unprintable characters as escape sequences.
92 Control-G becomes \007.
94 -w width Set the page width to WIDTH characters. */
101 #include <sys/types.h>
115 /* Used with start_position in the struct COLUMN described below.
116 If start_position == ANYWHERE, we aren't truncating columns and
117 can begin printing a column anywhere. Otherwise we must pad to
118 the horizontal position start_position. */
121 /* Each column has one of these structures allocated for it.
122 If we're only dealing with one file, fp is the same for all
125 The general strategy is to spend time setting up these column
126 structures (storing columns if necessary), after which printing
127 is a matter of flitting from column to column and calling
130 Parallel files, single files printing across in multiple
131 columns, and single files printing down in multiple columns all
132 fit the same printing loop.
134 print_func Function used to print lines in this column.
135 If we're storing this column it will be
136 print_stored(), Otherwise it will be read_line().
138 char_func Function used to process characters in this column.
139 If we're storing this column it will be store_char(),
140 otherwise it will be print_char().
142 current_line Index of the current entry in line_vector, which
143 contains the index of the first character of the
144 current line in buff[].
146 lines_stored Number of lines in this column which are stored in
149 lines_to_print If we're storing this column, lines_to_print is
150 the number of stored_lines which remain to be
151 printed. Otherwise it is the number of lines
152 we can print without exceeding lines_per_body.
154 start_position The horizontal position we want to be in before we
155 print the first character in this column.
157 numbered True means precede this column with a line number. */
161 FILE *fp; /* Input stream for this column. */
162 char *name; /* File name. */
166 ON_HOLD, /* Hit a form feed. */
168 } status; /* Status of the file pointer. */
169 int (*print_func) (); /* Func to print lines in this col. */
170 void (*char_func) (); /* Func to print/store chars in this col. */
171 int current_line; /* Index of current place in line_vector. */
172 int lines_stored; /* Number of lines stored in buff. */
173 int lines_to_print; /* No. lines stored or space left on page. */
174 int start_position; /* Horizontal position of first char. */
178 typedef struct COLUMN COLUMN;
180 #define NULLCOL (COLUMN *)0
182 static int char_to_clump (int c);
183 static int read_line (COLUMN *p);
184 static int print_page (void);
185 static int print_stored (COLUMN *p);
186 static int open_file (char *name, COLUMN *p);
187 static int skip_to_page (int page);
188 static void getoptarg (char *arg, char switch_char, char *character, int *number);
189 static void usage (int status);
190 static void print_files (int number_of_files, char **av);
191 static void init_header (char *filename, int desc);
192 static void init_store_cols (void);
193 static void store_columns (void);
194 static void balance (int total_stored);
195 static void store_char (int c);
196 static void pad_down (int lines);
197 static void read_rest_of_line (COLUMN *p);
198 static void print_char (int c);
199 static void cleanup (void);
201 /* The name under which this program was invoked. */
204 /* All of the columns to print. */
205 static COLUMN *column_vector;
207 /* When printing a single file in multiple downward columns,
208 we store the leftmost columns contiguously in buff.
209 To print a line from buff, get the index of the first char
210 from line_vector[i], and print up to line_vector[i + 1]. */
213 /* Index of the position in buff where the next character
215 static int buff_current;
217 /* The number of characters in buff.
218 Used for allocation of buff and to detect overflow of buff. */
219 static int buff_allocated;
221 /* Array of indices into buff.
222 Each entry is an index of the first character of a line.
223 This is used when storing lines to facilitate shuffling when
224 we do column balancing on the last page. */
225 static int *line_vector;
227 /* Array of horizonal positions.
228 For each line in line_vector, end_vector[line] is the horizontal
229 position we are in after printing that line. We keep track of this
230 so that we know how much we need to pad to prepare for the next
232 static int *end_vector;
234 /* (-m) True means we're printing multiple files in parallel. */
235 static int parallel_files = FALSE;
237 /* (-[0-9]+) True means we're given an option explicitly specifying
238 number of columns. Used to detect when this option is used with -m. */
239 static int explicit_columns = FALSE;
241 /* (-t) True means we're printing headers and footers. */
242 static int extremities = TRUE;
244 /* True means we need to print a header as soon as we know we've got input
245 to print after it. */
246 static int print_a_header;
248 /* (-h) True means we're using the standard header rather than a
249 customized one specified by the -h flag. */
250 static int standard_header = TRUE;
252 /* (-f) True means use formfeeds instead of newlines to separate pages. */
253 static int use_form_feed = FALSE;
255 /* True means we have read the standard input. */
256 static int have_read_stdin = FALSE;
258 /* True means the -a flag has been given. */
259 static int print_across_flag = FALSE;
261 /* True means we're printing one file in multiple (>1) downward columns. */
262 static int storing_columns = TRUE;
264 /* (-b) True means balance columns on the last page as Sys V does. */
265 static int balance_columns = FALSE;
267 /* (-l) Number of lines on a page, including header and footer lines. */
268 static int lines_per_page = 66;
270 /* Number of lines in the header and footer can be reset to 0 using
272 static int lines_per_header = 5;
273 static int lines_per_body;
274 static int lines_per_footer = 5;
276 /* (-w) Width in characters of the page. Does not include the width of
278 static int chars_per_line = 72;
280 /* Number of characters in a column. Based on the gutter and page widths. */
281 static int chars_per_column;
283 /* (-e) True means convert tabs to spaces on input. */
284 static int untabify_input = FALSE;
286 /* (-e) The input tab character. */
287 static char input_tab_char = '\t';
289 /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
290 where the leftmost column is 1. */
291 static int chars_per_input_tab = 8;
293 /* (-i) True means convert spaces to tabs on output. */
294 static int tabify_output = FALSE;
296 /* (-i) The output tab character. */
297 static char output_tab_char = '\t';
299 /* (-i) The width of the output tab. */
300 static int chars_per_output_tab = 8;
302 /* Keeps track of pending white space. When we hit a nonspace
303 character after some whitespace, we print whitespace, tabbing
304 if necessary to get to output_position + spaces_not_printed. */
305 static int spaces_not_printed;
307 /* Number of spaces between columns (though tabs can be used when possible to
308 use up the equivalent amount of space). Not sure if this is worth making
309 a flag for. BSD uses 0, Sys V uses 1. Sys V looks better. */
310 static int chars_per_gutter = 1;
312 /* (-o) Number of spaces in the left margin (tabs used when possible). */
313 static int chars_per_margin = 0;
315 /* Position where the next character will fall.
316 Leftmost position is 0 + chars_per_margin.
317 Rightmost position is chars_per_margin + chars_per_line - 1.
318 This is important for converting spaces to tabs on output. */
319 static int output_position;
321 /* Horizontal position relative to the current file.
322 (output_position depends on where we are on the page;
323 input_position depends on where we are in the file.)
324 Important for converting tabs to spaces on input. */
325 static int input_position;
327 /* Count number of failed opens so we can exit with non-zero
328 status if there were any. */
329 static int failed_opens = 0;
331 /* The horizontal position we'll be at after printing a tab character
332 of width c_ from the position h_. */
333 #define pos_after_tab(c_, h_) h_ - h_ % c_ + c_
335 /* The number of spaces taken up if we print a tab character with width
336 c_ from position h_. */
337 #define tab_width(c_, h_) - h_ % c_ + c_
339 /* (-NNN) Number of columns of text to print. */
340 static int columns = 1;
342 /* (+NNN) Page number on which to begin printing. */
343 static int first_page_number = 1;
345 /* Number of files open (not closed, not on hold). */
346 static int files_ready_to_read = 0;
348 /* Current page number. Displayed in header. */
349 static int page_number;
351 /* Current line number. Displayed when -n flag is specified.
353 When printing files in parallel (-m flag), line numbering is as follows:
357 When printing files across (-a flag), ...
361 Otherwise, line numbering is as follows:
364 static int line_number;
366 /* (-n) True means lines should be preceded by numbers. */
367 static int numbered_lines = FALSE;
369 /* (-n) Character which follows each line number. */
370 static char number_separator = '\t';
372 /* (-n) Width in characters of a line number. */
373 static int chars_per_number = 5;
375 /* Used when widening the first column to accommodate numbers -- only
376 needed when printing files in parallel. Includes width of both the
377 number and the number_separator. */
378 static int number_width;
380 /* Buffer sprintf uses to format a line number. */
381 static char *number_buff;
383 /* (-v) True means unprintable characters are printed as escape sequences.
384 control-g becomes \007. */
385 static int use_esc_sequence = FALSE;
387 /* (-c) True means unprintable characters are printed as control prefixes.
388 control-g becomes ^G. */
389 static int use_cntrl_prefix = FALSE;
391 /* (-d) True means output is double spaced. */
392 static int double_space = FALSE;
394 /* Number of files opened initially in init_files. Should be 1
395 unless we're printing multiple files in parallel. */
396 static int total_files = 0;
398 /* (-r) True means don't complain if we can't open a file. */
399 static int ignore_failed_opens = FALSE;
401 /* (-s) True means we separate columns with a specified character. */
402 static int use_column_separator = FALSE;
404 /* Character used to separate columns if the the -s flag has been specified. */
405 static char column_separator = '\t';
407 /* Number of separator characters waiting to be printed as soon as we
408 know that we have any input remaining to be printed. */
409 static int separators_not_printed;
411 /* Position we need to pad to, as soon as we know that we have input
412 remaining to be printed. */
413 static int padding_not_printed;
415 /* True means we should pad the end of the page. Remains false until we
416 know we have a page to print. */
417 static int pad_vertically;
419 /* (-h) String of characters used in place of the filename in the header. */
420 static char *custom_header;
422 /* String containing the date, filename or custom header, and "Page ". */
425 static int *clump_buff;
427 /* True means we truncate lines longer than chars_per_column. */
428 static int truncate_lines = FALSE;
430 /* If non-zero, display usage information and exit. */
431 static int show_help;
433 /* If non-zero, print the version on standard output then exit. */
434 static int show_version;
436 static struct option const long_options[] =
438 {"help", no_argument, &show_help, 1},
439 {"version", no_argument, &show_version, 1},
443 /* Return the number of columns that have either an open file or
447 cols_ready_to_print (void)
454 for (q = column_vector, i = 0; i < columns; ++q, ++i)
455 if (q->status == OPEN ||
456 (storing_columns && q->lines_stored > 0 && q->lines_to_print > 0))
462 main (int argc, char **argv)
469 program_name = argv[0];
472 file_names = (argc > 1
473 ? (char **) xmalloc ((argc - 1) * sizeof (char *))
478 c = getopt_long (argc, argv,
479 "-0123456789abcde::fFh:i::l:mn::o:rs::tvw:",
480 long_options, (int *) 0);
481 if (c == 1) /* Non-option argument. */
490 error (0, 0, _("`+' requires a numeric argument"));
493 /* FIXME: use strtol */
494 first_page_number = atoi (s);
498 file_names[n_files++] = optarg;
505 accum = accum * 10 + c - '0';
513 explicit_columns = TRUE;
527 case 0: /* getopt long option */
531 print_across_flag = TRUE;
532 storing_columns = FALSE;
535 balance_columns = TRUE;
538 use_cntrl_prefix = TRUE;
545 getoptarg (optarg, 'e', &input_tab_char,
546 &chars_per_input_tab);
547 /* Could check tab width > 0. */
548 untabify_input = TRUE;
552 use_form_feed = TRUE;
555 custom_header = optarg;
556 standard_header = FALSE;
560 getoptarg (optarg, 'i', &output_tab_char,
561 &chars_per_output_tab);
562 /* Could check tab width > 0. */
563 tabify_output = TRUE;
566 lines_per_page = atoi (optarg);
569 parallel_files = TRUE;
570 storing_columns = FALSE;
573 numbered_lines = TRUE;
575 getoptarg (optarg, 'n', &number_separator,
579 chars_per_margin = atoi (optarg);
582 ignore_failed_opens = TRUE;
585 use_column_separator = TRUE;
590 column_separator = *s;
593 fprintf (stderr, _("\
594 %s: extra characters in the argument to the `-s' option: `%s'\n"),
604 use_esc_sequence = TRUE;
607 chars_per_line = atoi (optarg);
617 printf ("pr - %s\n", version_string);
624 if (parallel_files && explicit_columns)
626 _("Cannot specify number of columns when printing in parallel."));
628 if (parallel_files && print_across_flag)
630 _("Cannot specify both printing across and printing in parallel."));
632 for ( ; optind < argc; optind++)
634 file_names[n_files++] = argv[optind];
639 /* No file arguments specified; read from standard input. */
640 print_files (0, (char **) 0);
645 print_files (n_files, file_names);
649 for (i=0; i<n_files; i++)
650 print_files (1, &file_names[i]);
656 if (have_read_stdin && fclose (stdin) == EOF)
657 error (1, errno, _("standard input"));
658 if (ferror (stdout) || fclose (stdout) == EOF)
659 error (1, errno, _("write error"));
660 if (failed_opens > 0)
665 /* Parse options of the form -scNNN.
667 Example: -nck, where 'n' is the option, c is the optional number
668 separator, and k is the optional width of the field used when printing
672 getoptarg (char *arg, char switch_char, char *character, int *number)
679 *number = atoi (arg);
682 fprintf (stderr, _("\
683 %s: extra characters in the argument to the `-%c' option: `%s'\n"),
684 program_name, switch_char, arg);
690 /* Set parameters related to formatting. */
693 init_parameters (int number_of_files)
695 int chars_used_by_number = 0;
697 lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
698 if (lines_per_body <= 0)
700 if (extremities == FALSE)
701 lines_per_body = lines_per_page;
704 lines_per_body = lines_per_body / 2;
706 /* If input is stdin, cannot print parallel files. BSD dumps core
708 if (number_of_files == 0)
709 parallel_files = FALSE;
712 columns = number_of_files;
714 /* Tabification is assumed for multiple columns. */
717 if (!use_column_separator)
718 truncate_lines = TRUE;
720 untabify_input = TRUE;
721 tabify_output = TRUE;
724 storing_columns = FALSE;
728 if (number_separator == input_tab_char)
730 number_width = chars_per_number +
731 tab_width (chars_per_input_tab,
732 (chars_per_margin + chars_per_number));
735 number_width = chars_per_number + 1;
736 /* The number is part of the column width unless we are
737 printing files in parallel. */
739 chars_used_by_number = number_width;
742 chars_per_column = (chars_per_line - chars_used_by_number -
743 (columns - 1) * chars_per_gutter) / columns;
745 if (chars_per_column < 1)
746 error (1, 0, _("page width too narrow"));
750 if (number_buff != (char *) 0)
752 number_buff = (char *)
753 xmalloc (2 * chars_per_number * sizeof (char));
756 /* Pick the maximum between the tab width and the width of an
758 if (clump_buff != (int *) 0)
760 clump_buff = (int *) xmalloc ((chars_per_input_tab > 4
761 ? chars_per_input_tab : 4) * sizeof (int));
764 /* Open the necessary files,
765 maintaining a COLUMN structure for each column.
767 With multiple files, each column p has a different p->fp.
768 With single files, each column p has the same p->fp.
769 Return 1 if (number_of_files > 0) and no files can be opened,
773 init_fps (int number_of_files, char **av)
782 if (column_vector != NULLCOL)
783 free ((char *) column_vector);
784 column_vector = (COLUMN *) xmalloc (columns * sizeof (COLUMN));
788 files_left = number_of_files;
789 for (p = column_vector; files_left--; ++p, ++av)
791 if (open_file (*av, p) == 0)
799 init_header ("", -1);
804 if (number_of_files > 0)
806 if (open_file (*av, p) == 0)
808 init_header (*av, fileno (p->fp));
812 p->name = _("standard input");
814 have_read_stdin = TRUE;
817 init_header ("", -1);
822 for (i = columns - 1, ++p; i; --i, ++p)
829 files_ready_to_read = total_files;
833 /* Determine print_func and char_func, the functions
834 used by each column for printing and/or storing.
836 Determine the horizontal position desired when we begin
837 printing a column (p->start_position). */
845 h = chars_per_margin;
847 if (use_column_separator)
851 /* When numbering lines of parallel files, we enlarge the
852 first column to accomodate the number. Looks better than
853 the Sys V approach. */
854 if (parallel_files && numbered_lines)
855 h_next = h + chars_per_column + number_width;
857 h_next = h + chars_per_column;
860 /* This loop takes care of all but the rightmost column. */
862 for (p = column_vector, i = 1; i < columns; ++p, ++i)
864 if (storing_columns) /* One file, multi columns down. */
866 p->char_func = store_char;
867 p->print_func = print_stored;
870 /* One file, multi columns across; or parallel files. */
872 p->char_func = print_char;
873 p->print_func = read_line;
876 /* Number only the first column when printing files in
878 p->numbered = numbered_lines && (!parallel_files || i == 1);
879 p->start_position = h;
881 /* If we're using separators, all start_positions are
882 ANYWHERE, except the first column's start_position when
885 if (use_column_separator)
892 h = h_next + chars_per_gutter;
893 h_next = h + chars_per_column;
897 /* The rightmost column.
899 Doesn't need to be stored unless we intend to balance
900 columns on the last page. */
901 if (storing_columns && balance_columns)
903 p->char_func = store_char;
904 p->print_func = print_stored;
908 p->char_func = print_char;
909 p->print_func = read_line;
912 p->numbered = numbered_lines && (!parallel_files || i == 1);
913 p->start_position = h;
916 /* Open a file. Return nonzero if successful, zero if failed. */
919 open_file (char *name, COLUMN *p)
921 if (!strcmp (name, "-"))
923 p->name = _("standard input");
930 p->fp = fopen (name, "r");
935 if (!ignore_failed_opens)
936 error (0, errno, "%s", name);
944 /* Close the file in P.
946 If we aren't dealing with multiple files in parallel, we change
947 the status of all columns in the column list to reflect the close. */
950 close_file (COLUMN *p)
955 if (p->status == CLOSED)
958 error (1, errno, "%s", p->name);
959 if (p->fp != stdin && fclose (p->fp) == EOF)
960 error (1, errno, "%s", p->name);
964 for (q = column_vector, i = columns; i; ++q, --i)
967 if (q->lines_stored == 0)
969 q->lines_to_print = 0;
976 p->lines_to_print = 0;
979 --files_ready_to_read;
982 /* Put a file on hold until we start a new page,
983 since we've hit a form feed.
985 If we aren't dealing with parallel files, we must change the
986 status of all columns in the column list. */
989 hold_file (COLUMN *p)
995 for (q = column_vector, i = columns; i; ++q, --i)
999 p->lines_to_print = 0;
1000 --files_ready_to_read;
1003 /* Undo hold_file -- go through the column list and change any
1004 ON_HOLD columns to OPEN. Used at the end of each page. */
1012 for (p = column_vector; i; --i, ++p)
1013 if (p->status == ON_HOLD)
1016 files_ready_to_read++;
1020 /* Print a single file, or multiple files in parallel.
1022 Set up the list of columns, opening the necessary files.
1023 Allocate space for storing columns, if necessary.
1024 Skip to first_page_number, if user has asked to skip leading pages.
1025 Determine which functions are appropriate to store/print lines
1027 Print the file(s). */
1030 print_files (int number_of_files, char **av)
1032 init_parameters (number_of_files);
1033 if (init_fps (number_of_files, av))
1035 if (storing_columns)
1038 if (first_page_number > 1)
1040 if (!skip_to_page (first_page_number))
1043 page_number = first_page_number;
1051 while (print_page ())
1055 /* Generous estimate of number of characters taken up by "Jun 7 00:08 " and
1057 #define CHARS_FOR_DATE_AND_PAGE 50
1059 /* Initialize header information.
1060 If DESC is non-negative, it is a file descriptor open to
1061 FILENAME for reading.
1063 Allocate space for a header string,
1064 Determine the time, insert file name or user-specified string.
1066 It might be nice to have a "blank headers" option, since
1067 pr -h "" still prints the date and page number. */
1070 init_header (char *filename, int desc)
1072 int chars_per_header;
1080 /* If parallel files or standard input, use current time. */
1081 if (desc < 0 || !strcmp (filename, "-") || fstat (desc, &st))
1082 st.st_mtime = time ((time_t *) 0);
1083 t = ctime (&st.st_mtime);
1085 t[16] = '\0'; /* Mark end of month and time string. */
1086 t[24] = '\0'; /* Mark end of year string. */
1088 middle = standard_header ? f : custom_header;
1090 chars_per_header = strlen (middle) + CHARS_FOR_DATE_AND_PAGE + 1;
1091 if (header != (char *) 0)
1093 header = (char *) xmalloc (chars_per_header * sizeof (char));
1095 sprintf (header, _("%s %s %s Page"), &t[4], &t[20], middle);
1098 /* Set things up for printing a page
1100 Scan through the columns ...
1101 Determine which are ready to print
1102 (i.e., which have lines stored or open files)
1103 Set p->lines_to_print appropriately
1104 (to p->lines_stored if we're storing, or lines_per_body
1105 if we're reading straight from the file)
1106 Keep track of this total so we know when to stop printing */
1114 if (storing_columns)
1117 for (j = columns - 1, p = column_vector; j; --j, ++p)
1119 p->lines_to_print = p->lines_stored;
1123 if (balance_columns)
1125 p->lines_to_print = p->lines_stored;
1127 /* Since we're not balancing columns, we don't need to store
1128 the rightmost column. Read it straight from the file. */
1131 if (p->status == OPEN)
1133 p->lines_to_print = lines_per_body;
1136 p->lines_to_print = 0;
1140 for (j = columns, p = column_vector; j; --j, ++p)
1141 if (p->status == OPEN)
1143 p->lines_to_print = lines_per_body;
1146 p->lines_to_print = 0;
1151 As long as there are lines left on the page and columns ready to print,
1152 Scan across the column list
1153 if the column has stored lines or the file is open
1154 pad to the appropriate spot
1156 pad the remainder of the page with \n or \f as requested
1157 reset the status of all files -- any files which where on hold because
1158 of formfeeds are now put back into the lineup. */
1164 int lines_left_on_page;
1167 /* Used as an accumulator (with | operator) of successive values of
1168 pad_vertically. The trick is to set pad_vertically
1169 to zero before each run through the inner loop, then after that
1170 loop, it tells us whether a line was actually printed (whether a
1171 newline needs to be output -- or two for double spacing). But those
1172 values have to be accumulated (in pv) so we can invoke pad_down
1173 properly after the outer loop completes. */
1178 if (cols_ready_to_print () == 0)
1182 print_a_header = TRUE;
1184 /* Don't pad unless we know a page was printed. */
1185 pad_vertically = FALSE;
1188 lines_left_on_page = lines_per_body;
1190 lines_left_on_page *= 2;
1192 while (lines_left_on_page > 0 && cols_ready_to_print () > 0)
1194 output_position = 0;
1195 spaces_not_printed = 0;
1196 separators_not_printed = 0;
1197 pad_vertically = FALSE;
1199 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1202 if (p->lines_to_print > 0)
1204 padding_not_printed = p->start_position;
1206 if (!(p->print_func) (p))
1207 read_rest_of_line (p);
1208 pv |= pad_vertically;
1210 if (use_column_separator)
1211 ++separators_not_printed;
1213 --p->lines_to_print;
1214 if (p->lines_to_print <= 0)
1216 if (cols_ready_to_print () <= 0)
1225 --lines_left_on_page;
1228 if (double_space && pv && extremities)
1231 --lines_left_on_page;
1235 pad_vertically = pv;
1237 if (pad_vertically && extremities)
1238 pad_down (lines_left_on_page + lines_per_footer);
1240 reset_status (); /* Change ON_HOLD to OPEN. */
1242 return TRUE; /* More pages to go. */
1245 /* Allocate space for storing columns.
1247 This is necessary when printing multiple columns from a single file.
1248 Lines are stored consecutively in buff, separated by '\0'.
1249 (We can't use a fixed offset since with the '-s' flag lines aren't
1252 We maintain a list (line_vector) of pointers to the beginnings
1253 of lines in buff. We allocate one more than the number of lines
1254 because the last entry tells us the index of the last character,
1255 which we need to know in order to print the last line in buff. */
1258 init_store_cols (void)
1260 int total_lines = lines_per_body * columns;
1261 int chars_if_truncate = total_lines * (chars_per_column + 1);
1263 if (line_vector != (int *) 0)
1264 free ((int *) line_vector);
1265 line_vector = (int *) xmalloc ((total_lines + 1) * sizeof (int *));
1267 if (end_vector != (int *) 0)
1268 free ((int *) end_vector);
1269 end_vector = (int *) xmalloc (total_lines * sizeof (int *));
1271 if (buff != (char *) 0)
1273 buff_allocated = use_column_separator ? 2 * chars_if_truncate
1274 : chars_if_truncate; /* Tune this. */
1275 buff = (char *) xmalloc (buff_allocated * sizeof (char));
1278 /* Store all but the rightmost column.
1279 (Used when printing a single file in multiple downward columns)
1282 set p->current_line to be the index in line_vector of the
1283 first line in the column
1284 For each line in the column
1285 store the line in buff
1286 add to line_vector the index of the line's first char
1287 buff_start is the index in buff of the first character in the
1291 store_columns (void)
1296 int last_col; /* The rightmost column which will be saved in buff */
1302 if (balance_columns)
1305 last_col = columns - 1;
1307 for (i = 1, p = column_vector; i <= last_col; ++i, ++p)
1308 p->lines_stored = 0;
1310 for (i = 1, p = column_vector; i <= last_col && files_ready_to_read;
1313 p->current_line = line;
1314 for (j = lines_per_body; j && files_ready_to_read; --j)
1316 if (p->status == OPEN) /* Redundant. Clean up. */
1320 if (!read_line (p, i))
1321 read_rest_of_line (p);
1323 if (p->status == OPEN
1324 || buff_start != buff_current)
1327 line_vector[line] = buff_start;
1328 end_vector[line++] = input_position;
1329 buff_start = buff_current;
1334 /* Keep track of the location of the last char in buff. */
1335 line_vector[line] = buff_start;
1337 if (balance_columns && p->lines_stored != lines_per_body)
1342 balance (int total_stored)
1348 for (i = 1, p = column_vector; i <= columns; ++i, ++p)
1350 lines = total_stored / columns;
1351 if (i <= total_stored % columns)
1354 p->lines_stored = lines;
1355 p->current_line = first_line;
1357 first_line += lines;
1361 /* Store a character in the buffer. */
1366 if (buff_current >= buff_allocated)
1368 /* May be too generous. */
1369 buff_allocated = 2 * buff_allocated;
1370 buff = (char *) xrealloc (buff, buff_allocated * sizeof (char));
1372 buff[buff_current++] = (char) c;
1381 sprintf (number_buff, "%*d", chars_per_number, line_number++);
1383 for (i = chars_per_number; i > 0; i--)
1384 (p->char_func) ((int) *s++);
1386 if (number_separator == input_tab_char)
1388 i = number_width - chars_per_number;
1390 (p->char_func) ((int) ' ');
1393 (p->char_func) ((int) number_separator);
1395 if (truncate_lines && !parallel_files)
1396 input_position += number_width;
1399 /* Print (or store) padding until the current horizontal position
1403 pad_across_to (int position)
1405 register int h = output_position;
1408 spaces_not_printed = position - output_position;
1411 while (++h <= position)
1413 output_position = position;
1417 /* Pad to the bottom of the page.
1419 If the user has requested a formfeed, use one.
1420 Otherwise, use newlines. */
1423 pad_down (int lines)
1430 for (i = lines; i; --i)
1434 /* Read the rest of the line.
1436 Read from the current column's file until an end of line is
1437 hit. Used when we've truncated a line and we no longer need
1438 to print or store its characters. */
1441 read_rest_of_line (COLUMN *p)
1446 while ((c = getc (f)) != '\n')
1461 /* If we're tabifying output,
1463 When print_char encounters white space it keeps track
1464 of our desired horizontal position and delays printing
1465 until this function is called. */
1468 print_white_space (void)
1471 register int h_old = output_position;
1472 register int goal = h_old + spaces_not_printed;
1474 while (goal - h_old > 1
1475 && (h_new = pos_after_tab (chars_per_output_tab, h_old)) <= goal)
1477 putchar (output_tab_char);
1480 while (++h_old <= goal)
1483 output_position = goal;
1484 spaces_not_printed = 0;
1487 /* Print column separators.
1489 We keep a count until we know that we'll be printing a line,
1490 then print_separators() is called. */
1493 print_separators (void)
1495 for (; separators_not_printed > 0; --separators_not_printed)
1496 print_char (column_separator);
1499 /* Print (or store, depending on p->char_func) a clump of N
1503 print_clump (COLUMN *p, int n, int *clump)
1506 (p->char_func) (*clump++);
1509 /* Print a character.
1511 If we're tabifying, all tabs have been converted to spaces by
1512 process_char(). Keep a count of consecutive spaces, and when
1513 a nonspace is encountered, call print_white_space() to print the
1514 required number of tabs and spaces. */
1523 ++spaces_not_printed;
1526 else if (spaces_not_printed > 0)
1527 print_white_space ();
1529 /* Nonprintables are assumed to have width 0, except '\b'. */
1541 /* Skip to page PAGE before printing. */
1544 skip_to_page (int page)
1549 for (n = 1; n < page; ++n)
1551 for (i = 1; i <= lines_per_body; ++i)
1553 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1554 read_rest_of_line (p);
1558 return files_ready_to_read > 0;
1563 Formfeeds are assumed to use up two lines at the beginning of
1570 fprintf (stdout, "\n\n");
1572 output_position = 0;
1573 pad_across_to (chars_per_margin);
1574 print_white_space ();
1576 fprintf (stdout, "%s %d\n\n\n", header, page_number++);
1578 print_a_header = FALSE;
1579 output_position = 0;
1582 /* Print (or store, if p->char_func is store_char()) a line.
1584 Read a character to determine whether we have a line or not.
1585 (We may hit EOF, \n, or \f)
1587 Once we know we have a line,
1588 set pad_vertically = TRUE, meaning it's safe
1589 to pad down at the end of the page, since we do have a page.
1590 print a header if needed.
1591 pad across to padding_not_printed if needed.
1592 print any separators which need to be printed.
1593 print a line number if it needs to be printed.
1595 Print the clump which corresponds to the first character.
1597 Enter a loop and keep printing until an end of line condition
1598 exists, or until we exceed chars_per_column.
1600 Return FALSE if we exceed chars_per_column before reading
1601 an end of line character, TRUE otherwise. */
1604 read_line (COLUMN *p)
1606 register int c, chars;
1607 int last_input_position;
1609 #ifdef lint /* Suppress `used before initialized' warning. */
1615 last_input_position = input_position;
1627 chars = char_to_clump (c);
1630 if (truncate_lines && input_position > chars_per_column)
1632 input_position = last_input_position;
1636 if (p->char_func != store_char)
1638 pad_vertically = TRUE;
1643 if (padding_not_printed != ANYWHERE)
1645 pad_across_to (padding_not_printed);
1646 padding_not_printed = ANYWHERE;
1649 if (use_column_separator)
1650 print_separators ();
1659 print_clump (p, chars, clump_buff);
1677 last_input_position = input_position;
1678 chars = char_to_clump (c);
1679 if (truncate_lines && input_position > chars_per_column)
1681 input_position = last_input_position;
1685 print_clump (p, chars, clump_buff);
1689 /* Print a line from buff.
1691 If this function has been called, we know we have something to
1692 print. Therefore we set pad_vertically to TRUE, print
1693 a header if necessary, pad across if necessary, and print
1694 separators if necessary.
1696 Return TRUE, meaning there is no need to call read_rest_of_line. */
1699 print_stored (COLUMN *p)
1701 int line = p->current_line++;
1702 register char *first = &buff[line_vector[line]];
1703 register char *last = &buff[line_vector[line + 1]];
1705 pad_vertically = TRUE;
1710 if (padding_not_printed != ANYWHERE)
1712 pad_across_to (padding_not_printed);
1713 padding_not_printed = ANYWHERE;
1716 if (use_column_separator)
1717 print_separators ();
1719 while (first != last)
1720 print_char (*first++);
1722 if (spaces_not_printed == 0)
1723 output_position = p->start_position + end_vector[line];
1728 /* Convert a character to the proper format and return the number of
1729 characters in the resulting clump. Increment input_position by
1730 the width of the clump.
1732 Tabs are converted to clumps of spaces.
1733 Nonprintable characters may be converted to clumps of escape
1734 sequences or control prefixes.
1736 Note: the width of a clump is not necessarily equal to the number of
1737 characters in clump_buff. (e.g, the width of '\b' is -1, while the
1738 number of characters is 1.) */
1741 char_to_clump (int c)
1743 register int *s = clump_buff;
1749 if (c == input_tab_char)
1751 width = tab_width (chars_per_input_tab, input_position);
1755 for (i = width; i; --i)
1766 else if (!ISPRINT (c))
1768 if (use_esc_sequence)
1773 sprintf (esc_buff, "%03o", c);
1774 for (i = 0; i <= 2; ++i)
1775 *s++ = (int) esc_buff[i];
1777 else if (use_cntrl_prefix)
1791 sprintf (esc_buff, "%03o", c);
1792 for (i = 0; i <= 2; ++i)
1793 *s++ = (int) esc_buff[i];
1816 input_position += width;
1820 /* We've just printed some files and need to clean up things before
1821 looking for more options and printing the next batch of files.
1823 Free everything we've xmalloc'ed, except `header'. */
1833 free (column_vector);
1842 /* Complain, print a usage message, and die. */
1848 fprintf (stderr, _("Try `%s --help' for more information.\n"),
1853 Usage: %s [OPTION]... [FILE]...\n\
1857 Paginate or columnate FILE(s) for printing.\n\
1859 +PAGE begin printing with page PAGE\n\
1860 -COLUMN produce COLUMN-column output and print columns down\n\
1861 -F, -f simulate formfeed with newlines on output\n\
1862 -a print columns across rather than down\n\
1863 -b balance columns on the last page\n\
1864 -c use hat notation (^G) and octal backslash notation\n\
1865 -d double space the output\n\
1866 -e[CHAR[WIDTH]] expand input CHARs (TABs) to tab WIDTH (8)\n\
1867 -h HEADER use HEADER instead of filename in page headers\n\
1868 -i[CHAR[WIDTH]] replace spaces with CHARs (TABs) to tab WIDTH (8)\n\
1869 -l PAGE_LENGTH set the page length to PAGE_LENGTH (66) lines\n\
1870 -m print all files in parallel, one in each column\n\
1871 -n[SEP[DIGITS]] number lines, use DIGITS (5) digits, then SEP (TAB)\n\
1872 -o MARGIN offset each line with MARGIN spaces (do not affect -w)\n\
1873 -r inhibit warning when a file cannot be opened\n\
1874 -s[SEP] separate columns by character SEP (TAB)\n\
1875 -t inhibit 5-line page headers and trailers\n\
1876 -v use octal backslash notation\n\
1877 -w PAGE_WIDTH set page width to PAGE_WIDTH (72) columns\n\
1878 --help display this help and exit\n\
1879 --version output version information and exit\n\
1881 -t implied by -l N when N < 10. Without -s, columns are separated by\n\
1882 spaces. With no FILE, or when FILE is -, read standard input.\n\