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>
110 static int char_to_clump ();
111 static int read_line ();
112 static int print_page ();
113 static int print_stored ();
114 static int open_file ();
115 static int skip_to_page ();
116 static void getoptarg ();
117 static void usage ();
118 static void print_files ();
119 static void init_header ();
120 static void init_store_cols ();
121 static void store_columns ();
122 static void balance ();
123 static void store_char ();
124 static void pad_down ();
125 static void read_rest_of_line ();
126 static void print_char ();
127 static void cleanup ();
134 /* Used with start_position in the struct COLUMN described below.
135 If start_position == ANYWHERE, we aren't truncating columns and
136 can begin printing a column anywhere. Otherwise we must pad to
137 the horizontal position start_position. */
140 /* Each column has one of these structures allocated for it.
141 If we're only dealing with one file, fp is the same for all
144 The general strategy is to spend time setting up these column
145 structures (storing columns if necessary), after which printing
146 is a matter of flitting from column to column and calling
149 Parallel files, single files printing across in multiple
150 columns, and single files printing down in multiple columns all
151 fit the same printing loop.
153 print_func Function used to print lines in this column.
154 If we're storing this column it will be
155 print_stored(), Otherwise it will be read_line().
157 char_func Function used to process characters in this column.
158 If we're storing this column it will be store_char(),
159 otherwise it will be print_char().
161 current_line Index of the current entry in line_vector, which
162 contains the index of the first character of the
163 current line in buff[].
165 lines_stored Number of lines in this column which are stored in
168 lines_to_print If we're storing this column, lines_to_print is
169 the number of stored_lines which remain to be
170 printed. Otherwise it is the number of lines
171 we can print without exceeding lines_per_body.
173 start_position The horizontal position we want to be in before we
174 print the first character in this column.
176 numbered True means precede this column with a line number. */
180 FILE *fp
; /* Input stream for this column. */
181 char *name
; /* File name. */
185 ON_HOLD
, /* Hit a form feed. */
187 } status
; /* Status of the file pointer. */
188 int (*print_func
) (); /* Func to print lines in this col. */
189 void (*char_func
) (); /* Func to print/store chars in this col. */
190 int current_line
; /* Index of current place in line_vector. */
191 int lines_stored
; /* Number of lines stored in buff. */
192 int lines_to_print
; /* No. lines stored or space left on page. */
193 int start_position
; /* Horizontal position of first char. */
197 typedef struct COLUMN COLUMN
;
199 #define NULLCOL (COLUMN *)0
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 ()
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))
471 program_name
= argv
[0];
474 file_names
= (argc
> 1
475 ? (char **) xmalloc ((argc
- 1) * sizeof (char *))
480 c
= getopt_long (argc
, argv
,
481 "-0123456789abcde::fFh:i::l:mn::o:rs::tvw:",
482 long_options
, (int *) 0);
483 if (c
== 1) /* Non-option argument. */
492 error (0, 0, "`+' requires a numeric argument");
495 /* FIXME: use strtol */
496 first_page_number
= atoi (s
);
500 file_names
[n_files
++] = optarg
;
507 accum
= accum
* 10 + c
- '0';
515 explicit_columns
= TRUE
;
529 case 0: /* getopt long option */
533 print_across_flag
= TRUE
;
534 storing_columns
= FALSE
;
537 balance_columns
= TRUE
;
540 use_cntrl_prefix
= TRUE
;
547 getoptarg (optarg
, 'e', &input_tab_char
,
548 &chars_per_input_tab
);
549 /* Could check tab width > 0. */
550 untabify_input
= TRUE
;
554 use_form_feed
= TRUE
;
557 custom_header
= optarg
;
558 standard_header
= FALSE
;
562 getoptarg (optarg
, 'i', &output_tab_char
,
563 &chars_per_output_tab
);
564 /* Could check tab width > 0. */
565 tabify_output
= TRUE
;
568 lines_per_page
= atoi (optarg
);
571 parallel_files
= TRUE
;
572 storing_columns
= FALSE
;
575 numbered_lines
= TRUE
;
577 getoptarg (optarg
, 'n', &number_separator
,
581 chars_per_margin
= atoi (optarg
);
584 ignore_failed_opens
= TRUE
;
587 use_column_separator
= TRUE
;
592 column_separator
= *s
;
596 %s: extra characters in the argument to the `-s' option: `%s'\n",
606 use_esc_sequence
= TRUE
;
609 chars_per_line
= atoi (optarg
);
619 printf ("pr - %s\n", version_string
);
626 if (parallel_files
&& explicit_columns
)
628 "Cannot specify number of columns when printing in parallel.");
630 if (parallel_files
&& print_across_flag
)
632 "Cannot specify both printing across and printing in parallel.");
634 for ( ; optind
< argc
; optind
++)
636 file_names
[n_files
++] = argv
[optind
];
641 /* No file arguments specified; read from standard input. */
642 print_files (0, (char **) 0);
647 print_files (n_files
, file_names
);
651 for (i
=0; i
<n_files
; i
++)
652 print_files (1, &file_names
[i
]);
658 if (have_read_stdin
&& fclose (stdin
) == EOF
)
659 error (1, errno
, "standard input");
660 if (ferror (stdout
) || fclose (stdout
) == EOF
)
661 error (1, errno
, "write error");
662 if (failed_opens
> 0)
667 /* Parse options of the form -scNNN.
669 Example: -nck, where 'n' is the option, c is the optional number
670 separator, and k is the optional width of the field used when printing
674 getoptarg (arg
, switch_char
, character
, number
)
675 char *arg
, switch_char
, *character
;
683 *number
= atoi (arg
);
687 %s: extra characters in the argument to the `-%c' option: `%s'\n",
688 program_name
, switch_char
, arg
);
694 /* Set parameters related to formatting. */
697 init_parameters (number_of_files
)
700 int chars_used_by_number
= 0;
702 lines_per_body
= lines_per_page
- lines_per_header
- lines_per_footer
;
703 if (lines_per_body
<= 0)
705 if (extremities
== FALSE
)
706 lines_per_body
= lines_per_page
;
709 lines_per_body
= lines_per_body
/ 2;
711 /* If input is stdin, cannot print parallel files. BSD dumps core
713 if (number_of_files
== 0)
714 parallel_files
= FALSE
;
717 columns
= number_of_files
;
719 /* Tabification is assumed for multiple columns. */
722 if (!use_column_separator
)
723 truncate_lines
= TRUE
;
725 untabify_input
= TRUE
;
726 tabify_output
= TRUE
;
729 storing_columns
= FALSE
;
733 if (number_separator
== input_tab_char
)
735 number_width
= chars_per_number
+
736 tab_width (chars_per_input_tab
,
737 (chars_per_margin
+ chars_per_number
));
740 number_width
= chars_per_number
+ 1;
741 /* The number is part of the column width unless we are
742 printing files in parallel. */
744 chars_used_by_number
= number_width
;
747 chars_per_column
= (chars_per_line
- chars_used_by_number
-
748 (columns
- 1) * chars_per_gutter
) / columns
;
750 if (chars_per_column
< 1)
751 error (1, 0, "page width too narrow");
755 if (number_buff
!= (char *) 0)
757 number_buff
= (char *)
758 xmalloc (2 * chars_per_number
* sizeof (char));
761 /* Pick the maximum between the tab width and the width of an
763 if (clump_buff
!= (int *) 0)
765 clump_buff
= (int *) xmalloc ((chars_per_input_tab
> 4
766 ? chars_per_input_tab
: 4) * sizeof (int));
769 /* Open the necessary files,
770 maintaining a COLUMN structure for each column.
772 With multiple files, each column p has a different p->fp.
773 With single files, each column p has the same p->fp.
774 Return 1 if (number_of_files > 0) and no files can be opened,
778 init_fps (number_of_files
, av
)
789 if (column_vector
!= NULLCOL
)
790 free ((char *) column_vector
);
791 column_vector
= (COLUMN
*) xmalloc (columns
* sizeof (COLUMN
));
795 files_left
= number_of_files
;
796 for (p
= column_vector
; files_left
--; ++p
, ++av
)
798 if (open_file (*av
, p
) == 0)
806 init_header ("", -1);
811 if (number_of_files
> 0)
813 if (open_file (*av
, p
) == 0)
815 init_header (*av
, fileno (p
->fp
));
819 p
->name
= "standard input";
821 have_read_stdin
= TRUE
;
824 init_header ("", -1);
829 for (i
= columns
- 1, ++p
; i
; --i
, ++p
)
836 files_ready_to_read
= total_files
;
840 /* Determine print_func and char_func, the functions
841 used by each column for printing and/or storing.
843 Determine the horizontal position desired when we begin
844 printing a column (p->start_position). */
852 h
= chars_per_margin
;
854 if (use_column_separator
)
858 /* When numbering lines of parallel files, we enlarge the
859 first column to accomodate the number. Looks better than
860 the Sys V approach. */
861 if (parallel_files
&& numbered_lines
)
862 h_next
= h
+ chars_per_column
+ number_width
;
864 h_next
= h
+ chars_per_column
;
867 /* This loop takes care of all but the rightmost column. */
869 for (p
= column_vector
, i
= 1; i
< columns
; ++p
, ++i
)
871 if (storing_columns
) /* One file, multi columns down. */
873 p
->char_func
= store_char
;
874 p
->print_func
= print_stored
;
877 /* One file, multi columns across; or parallel files. */
879 p
->char_func
= print_char
;
880 p
->print_func
= read_line
;
883 /* Number only the first column when printing files in
885 p
->numbered
= numbered_lines
&& (!parallel_files
|| i
== 1);
886 p
->start_position
= h
;
888 /* If we're using separators, all start_positions are
889 ANYWHERE, except the first column's start_position when
892 if (use_column_separator
)
899 h
= h_next
+ chars_per_gutter
;
900 h_next
= h
+ chars_per_column
;
904 /* The rightmost column.
906 Doesn't need to be stored unless we intend to balance
907 columns on the last page. */
908 if (storing_columns
&& balance_columns
)
910 p
->char_func
= store_char
;
911 p
->print_func
= print_stored
;
915 p
->char_func
= print_char
;
916 p
->print_func
= read_line
;
919 p
->numbered
= numbered_lines
&& (!parallel_files
|| i
== 1);
920 p
->start_position
= h
;
923 /* Open a file. Return nonzero if successful, zero if failed. */
930 if (!strcmp (name
, "-"))
932 p
->name
= "standard input";
939 p
->fp
= fopen (name
, "r");
944 if (!ignore_failed_opens
)
945 error (0, errno
, "%s", name
);
953 /* Close the file in P.
955 If we aren't dealing with multiple files in parallel, we change
956 the status of all columns in the column list to reflect the close. */
965 if (p
->status
== CLOSED
)
968 error (1, errno
, "%s", p
->name
);
969 if (p
->fp
!= stdin
&& fclose (p
->fp
) == EOF
)
970 error (1, errno
, "%s", p
->name
);
974 for (q
= column_vector
, i
= columns
; i
; ++q
, --i
)
977 if (q
->lines_stored
== 0)
979 q
->lines_to_print
= 0;
986 p
->lines_to_print
= 0;
989 --files_ready_to_read
;
992 /* Put a file on hold until we start a new page,
993 since we've hit a form feed.
995 If we aren't dealing with parallel files, we must change the
996 status of all columns in the column list. */
1005 if (!parallel_files
)
1006 for (q
= column_vector
, i
= columns
; i
; ++q
, --i
)
1007 q
->status
= ON_HOLD
;
1009 p
->status
= ON_HOLD
;
1010 p
->lines_to_print
= 0;
1011 --files_ready_to_read
;
1014 /* Undo hold_file -- go through the column list and change any
1015 ON_HOLD columns to OPEN. Used at the end of each page. */
1023 for (p
= column_vector
; i
; --i
, ++p
)
1024 if (p
->status
== ON_HOLD
)
1027 files_ready_to_read
++;
1031 /* Print a single file, or multiple files in parallel.
1033 Set up the list of columns, opening the necessary files.
1034 Allocate space for storing columns, if necessary.
1035 Skip to first_page_number, if user has asked to skip leading pages.
1036 Determine which functions are appropriate to store/print lines
1038 Print the file(s). */
1041 print_files (number_of_files
, av
)
1042 int number_of_files
;
1045 init_parameters (number_of_files
);
1046 if (init_fps (number_of_files
, av
))
1048 if (storing_columns
)
1051 if (first_page_number
> 1)
1053 if (!skip_to_page (first_page_number
))
1056 page_number
= first_page_number
;
1064 while (print_page ())
1068 /* Generous estimate of number of characters taken up by "Jun 7 00:08 " and
1070 #define CHARS_FOR_DATE_AND_PAGE 50
1072 /* Initialize header information.
1073 If DESC is non-negative, it is a file descriptor open to
1074 FILENAME for reading.
1076 Allocate space for a header string,
1077 Determine the time, insert file name or user-specified string.
1079 It might be nice to have a "blank headers" option, since
1080 pr -h "" still prints the date and page number. */
1083 init_header (filename
, desc
)
1087 int chars_per_header
;
1095 /* If parallel files or standard input, use current time. */
1096 if (desc
< 0 || !strcmp (filename
, "-") || fstat (desc
, &st
))
1097 st
.st_mtime
= time ((time_t *) 0);
1098 t
= ctime (&st
.st_mtime
);
1100 t
[16] = '\0'; /* Mark end of month and time string. */
1101 t
[24] = '\0'; /* Mark end of year string. */
1103 middle
= standard_header
? f
: custom_header
;
1105 chars_per_header
= strlen (middle
) + CHARS_FOR_DATE_AND_PAGE
+ 1;
1106 if (header
!= (char *) 0)
1108 header
= (char *) xmalloc (chars_per_header
* sizeof (char));
1110 sprintf (header
, "%s %s %s Page", &t
[4], &t
[20], middle
);
1113 /* Set things up for printing a page
1115 Scan through the columns ...
1116 Determine which are ready to print
1117 (i.e., which have lines stored or open files)
1118 Set p->lines_to_print appropriately
1119 (to p->lines_stored if we're storing, or lines_per_body
1120 if we're reading straight from the file)
1121 Keep track of this total so we know when to stop printing */
1129 if (storing_columns
)
1132 for (j
= columns
- 1, p
= column_vector
; j
; --j
, ++p
)
1134 p
->lines_to_print
= p
->lines_stored
;
1138 if (balance_columns
)
1140 p
->lines_to_print
= p
->lines_stored
;
1142 /* Since we're not balancing columns, we don't need to store
1143 the rightmost column. Read it straight from the file. */
1146 if (p
->status
== OPEN
)
1148 p
->lines_to_print
= lines_per_body
;
1151 p
->lines_to_print
= 0;
1155 for (j
= columns
, p
= column_vector
; j
; --j
, ++p
)
1156 if (p
->status
== OPEN
)
1158 p
->lines_to_print
= lines_per_body
;
1161 p
->lines_to_print
= 0;
1166 As long as there are lines left on the page and columns ready to print,
1167 Scan across the column list
1168 if the column has stored lines or the file is open
1169 pad to the appropriate spot
1171 pad the remainder of the page with \n or \f as requested
1172 reset the status of all files -- any files which where on hold because
1173 of formfeeds are now put back into the lineup. */
1179 int lines_left_on_page
;
1182 /* Used as an accumulator (with | operator) of successive values of
1183 pad_vertically. The trick is to set pad_vertically
1184 to zero before each run through the inner loop, then after that
1185 loop, it tells us whether a line was actually printed (whether a
1186 newline needs to be output -- or two for double spacing). But those
1187 values have to be accumulated (in pv) so we can invoke pad_down
1188 properly after the outer loop completes. */
1193 if (cols_ready_to_print () == 0)
1197 print_a_header
= TRUE
;
1199 /* Don't pad unless we know a page was printed. */
1200 pad_vertically
= FALSE
;
1203 lines_left_on_page
= lines_per_body
;
1205 lines_left_on_page
*= 2;
1207 while (lines_left_on_page
> 0 && cols_ready_to_print () > 0)
1209 output_position
= 0;
1210 spaces_not_printed
= 0;
1211 separators_not_printed
= 0;
1212 pad_vertically
= FALSE
;
1214 for (j
= 1, p
= column_vector
; j
<= columns
; ++j
, ++p
)
1217 if (p
->lines_to_print
> 0)
1219 padding_not_printed
= p
->start_position
;
1221 if (!(p
->print_func
) (p
))
1222 read_rest_of_line (p
);
1223 pv
|= pad_vertically
;
1225 if (use_column_separator
)
1226 ++separators_not_printed
;
1228 --p
->lines_to_print
;
1229 if (p
->lines_to_print
<= 0)
1231 if (cols_ready_to_print () <= 0)
1240 --lines_left_on_page
;
1243 if (double_space
&& pv
&& extremities
)
1246 --lines_left_on_page
;
1250 pad_vertically
= pv
;
1252 if (pad_vertically
&& extremities
)
1253 pad_down (lines_left_on_page
+ lines_per_footer
);
1255 reset_status (); /* Change ON_HOLD to OPEN. */
1257 return TRUE
; /* More pages to go. */
1260 /* Allocate space for storing columns.
1262 This is necessary when printing multiple columns from a single file.
1263 Lines are stored consecutively in buff, separated by '\0'.
1264 (We can't use a fixed offset since with the '-s' flag lines aren't
1267 We maintain a list (line_vector) of pointers to the beginnings
1268 of lines in buff. We allocate one more than the number of lines
1269 because the last entry tells us the index of the last character,
1270 which we need to know in order to print the last line in buff. */
1275 int total_lines
= lines_per_body
* columns
;
1276 int chars_if_truncate
= total_lines
* (chars_per_column
+ 1);
1278 if (line_vector
!= (int *) 0)
1279 free ((int *) line_vector
);
1280 line_vector
= (int *) xmalloc ((total_lines
+ 1) * sizeof (int *));
1282 if (end_vector
!= (int *) 0)
1283 free ((int *) end_vector
);
1284 end_vector
= (int *) xmalloc (total_lines
* sizeof (int *));
1286 if (buff
!= (char *) 0)
1288 buff_allocated
= use_column_separator
? 2 * chars_if_truncate
1289 : chars_if_truncate
; /* Tune this. */
1290 buff
= (char *) xmalloc (buff_allocated
* sizeof (char));
1293 /* Store all but the rightmost column.
1294 (Used when printing a single file in multiple downward columns)
1297 set p->current_line to be the index in line_vector of the
1298 first line in the column
1299 For each line in the column
1300 store the line in buff
1301 add to line_vector the index of the line's first char
1302 buff_start is the index in buff of the first character in the
1311 int last_col
; /* The rightmost column which will be saved in buff */
1317 if (balance_columns
)
1320 last_col
= columns
- 1;
1322 for (i
= 1, p
= column_vector
; i
<= last_col
; ++i
, ++p
)
1323 p
->lines_stored
= 0;
1325 for (i
= 1, p
= column_vector
; i
<= last_col
&& files_ready_to_read
;
1328 p
->current_line
= line
;
1329 for (j
= lines_per_body
; j
&& files_ready_to_read
; --j
)
1331 if (p
->status
== OPEN
) /* Redundant. Clean up. */
1335 if (!read_line (p
, i
))
1336 read_rest_of_line (p
);
1338 if (p
->status
== OPEN
1339 || buff_start
!= buff_current
)
1342 line_vector
[line
] = buff_start
;
1343 end_vector
[line
++] = input_position
;
1344 buff_start
= buff_current
;
1349 /* Keep track of the location of the last char in buff. */
1350 line_vector
[line
] = buff_start
;
1352 if (balance_columns
&& p
->lines_stored
!= lines_per_body
)
1357 balance (total_stored
)
1364 for (i
= 1, p
= column_vector
; i
<= columns
; ++i
, ++p
)
1366 lines
= total_stored
/ columns
;
1367 if (i
<= total_stored
% columns
)
1370 p
->lines_stored
= lines
;
1371 p
->current_line
= first_line
;
1373 first_line
+= lines
;
1377 /* Store a character in the buffer. */
1383 if (buff_current
>= buff_allocated
)
1385 /* May be too generous. */
1386 buff_allocated
= 2 * buff_allocated
;
1387 buff
= (char *) xrealloc (buff
, buff_allocated
* sizeof (char));
1389 buff
[buff_current
++] = (char) c
;
1399 sprintf (number_buff
, "%*d", chars_per_number
, line_number
++);
1401 for (i
= chars_per_number
; i
> 0; i
--)
1402 (p
->char_func
) ((int) *s
++);
1404 if (number_separator
== input_tab_char
)
1406 i
= number_width
- chars_per_number
;
1408 (p
->char_func
) ((int) ' ');
1411 (p
->char_func
) ((int) number_separator
);
1413 if (truncate_lines
&& !parallel_files
)
1414 input_position
+= number_width
;
1417 /* Print (or store) padding until the current horizontal position
1421 pad_across_to (position
)
1424 register int h
= output_position
;
1427 spaces_not_printed
= position
- output_position
;
1430 while (++h
<= position
)
1432 output_position
= position
;
1436 /* Pad to the bottom of the page.
1438 If the user has requested a formfeed, use one.
1439 Otherwise, use newlines. */
1450 for (i
= lines
; i
; --i
)
1454 /* Read the rest of the line.
1456 Read from the current column's file until an end of line is
1457 hit. Used when we've truncated a line and we no longer need
1458 to print or store its characters. */
1461 read_rest_of_line (p
)
1467 while ((c
= getc (f
)) != '\n')
1482 /* If we're tabifying output,
1484 When print_char encounters white space it keeps track
1485 of our desired horizontal position and delays printing
1486 until this function is called. */
1489 print_white_space ()
1492 register int h_old
= output_position
;
1493 register int goal
= h_old
+ spaces_not_printed
;
1495 while (goal
- h_old
> 1
1496 && (h_new
= pos_after_tab (chars_per_output_tab
, h_old
)) <= goal
)
1498 putchar (output_tab_char
);
1501 while (++h_old
<= goal
)
1504 output_position
= goal
;
1505 spaces_not_printed
= 0;
1508 /* Print column separators.
1510 We keep a count until we know that we'll be printing a line,
1511 then print_separators() is called. */
1516 for (; separators_not_printed
> 0; --separators_not_printed
)
1517 print_char (column_separator
);
1520 /* Print (or store, depending on p->char_func) a clump of N
1524 print_clump (p
, n
, clump
)
1530 (p
->char_func
) (*clump
++);
1533 /* Print a character.
1535 If we're tabifying, all tabs have been converted to spaces by
1536 process_char(). Keep a count of consecutive spaces, and when
1537 a nonspace is encountered, call print_white_space() to print the
1538 required number of tabs and spaces. */
1548 ++spaces_not_printed
;
1551 else if (spaces_not_printed
> 0)
1552 print_white_space ();
1554 /* Nonprintables are assumed to have width 0, except '\b'. */
1566 /* Skip to page PAGE before printing. */
1575 for (n
= 1; n
< page
; ++n
)
1577 for (i
= 1; i
<= lines_per_body
; ++i
)
1579 for (j
= 1, p
= column_vector
; j
<= columns
; ++j
, ++p
)
1580 read_rest_of_line (p
);
1584 return files_ready_to_read
> 0;
1589 Formfeeds are assumed to use up two lines at the beginning of
1596 fprintf (stdout
, "\n\n");
1598 output_position
= 0;
1599 pad_across_to (chars_per_margin
);
1600 print_white_space ();
1602 fprintf (stdout
, "%s %d\n\n\n", header
, page_number
++);
1604 print_a_header
= FALSE
;
1605 output_position
= 0;
1608 /* Print (or store, if p->char_func is store_char()) a line.
1610 Read a character to determine whether we have a line or not.
1611 (We may hit EOF, \n, or \f)
1613 Once we know we have a line,
1614 set pad_vertically = TRUE, meaning it's safe
1615 to pad down at the end of the page, since we do have a page.
1616 print a header if needed.
1617 pad across to padding_not_printed if needed.
1618 print any separators which need to be printed.
1619 print a line number if it needs to be printed.
1621 Print the clump which corresponds to the first character.
1623 Enter a loop and keep printing until an end of line condition
1624 exists, or until we exceed chars_per_column.
1626 Return FALSE if we exceed chars_per_column before reading
1627 an end of line character, TRUE otherwise. */
1633 register int c
, chars
;
1634 int last_input_position
;
1638 last_input_position
= input_position
;
1650 chars
= char_to_clump (c
);
1653 if (truncate_lines
&& input_position
> chars_per_column
)
1655 input_position
= last_input_position
;
1659 if (p
->char_func
!= store_char
)
1661 pad_vertically
= TRUE
;
1666 if (padding_not_printed
!= ANYWHERE
)
1668 pad_across_to (padding_not_printed
);
1669 padding_not_printed
= ANYWHERE
;
1672 if (use_column_separator
)
1673 print_separators ();
1682 print_clump (p
, chars
, clump_buff
);
1700 last_input_position
= input_position
;
1701 chars
= char_to_clump (c
);
1702 if (truncate_lines
&& input_position
> chars_per_column
)
1704 input_position
= last_input_position
;
1708 print_clump (p
, chars
, clump_buff
);
1712 /* Print a line from buff.
1714 If this function has been called, we know we have something to
1715 print. Therefore we set pad_vertically to TRUE, print
1716 a header if necessary, pad across if necessary, and print
1717 separators if necessary.
1719 Return TRUE, meaning there is no need to call read_rest_of_line. */
1725 int line
= p
->current_line
++;
1726 register char *first
= &buff
[line_vector
[line
]];
1727 register char *last
= &buff
[line_vector
[line
+ 1]];
1729 pad_vertically
= TRUE
;
1734 if (padding_not_printed
!= ANYWHERE
)
1736 pad_across_to (padding_not_printed
);
1737 padding_not_printed
= ANYWHERE
;
1740 if (use_column_separator
)
1741 print_separators ();
1743 while (first
!= last
)
1744 print_char (*first
++);
1746 if (spaces_not_printed
== 0)
1747 output_position
= p
->start_position
+ end_vector
[line
];
1752 /* Convert a character to the proper format and return the number of
1753 characters in the resulting clump. Increment input_position by
1754 the width of the clump.
1756 Tabs are converted to clumps of spaces.
1757 Nonprintable characters may be converted to clumps of escape
1758 sequences or control prefixes.
1760 Note: the width of a clump is not necessarily equal to the number of
1761 characters in clump_buff. (e.g, the width of '\b' is -1, while the
1762 number of characters is 1.) */
1768 register int *s
= clump_buff
;
1774 if (c
== input_tab_char
)
1776 width
= tab_width (chars_per_input_tab
, input_position
);
1780 for (i
= width
; i
; --i
)
1791 else if (!ISPRINT (c
))
1793 if (use_esc_sequence
)
1798 sprintf (esc_buff
, "%03o", c
);
1799 for (i
= 0; i
<= 2; ++i
)
1800 *s
++ = (int) esc_buff
[i
];
1802 else if (use_cntrl_prefix
)
1816 sprintf (esc_buff
, "%03o", c
);
1817 for (i
= 0; i
<= 2; ++i
)
1818 *s
++ = (int) esc_buff
[i
];
1841 input_position
+= width
;
1845 /* We've just printed some files and need to clean up things before
1846 looking for more options and printing the next batch of files.
1848 Free everything we've xmalloc'ed, except `header'. */
1858 free (column_vector
);
1867 /* Complain, print a usage message, and die. */
1874 fprintf (stderr
, "Try `%s --help' for more information.\n",
1879 Usage: %s [OPTION]... [FILE]...\n\
1883 Paginate or columnate FILE(s) for printing.\n\
1885 +PAGE begin printing with page PAGE\n\
1886 -COLUMN produce COLUMN-column output and print columns down\n\
1887 -F, -f simulate formfeed with newlines on output\n\
1888 -a print columns across rather than down\n\
1889 -b balance columns on the last page\n\
1890 -c use hat notation (^G) and octal backslash notation\n\
1891 -d double space the output\n\
1892 -e[CHAR[WIDTH]] expand input CHARs (TABs) to tab WIDTH (8)\n\
1893 -h HEADER use HEADER instead of filename in page headers\n\
1894 -i[CHAR[WIDTH]] replace spaces with CHARs (TABs) to tab WIDTH (8)\n\
1895 -l PAGE_LENGTH set the page length to PAGE_LENGTH (66) lines\n\
1896 -m print all files in parallel, one in each column\n\
1897 -n[SEP[DIGITS]] number lines, use DIGITS (5) digits, then SEP (TAB)\n\
1898 -o MARGIN offset each line with MARGIN spaces (do not affect -w)\n\
1899 -r inhibit warning when a file cannot be opened\n\
1900 -s[SEP] separate columns by character SEP (TAB)\n\
1901 -t inhibit 5-line page headers and trailers\n\
1902 -v use octal backslash notation\n\
1903 -w PAGE_WIDTH set page width to PAGE_WIDTH (72) columns\n\
1904 --help display this help and exit\n\
1905 --version output version information and exit\n\
1907 -t implied by -l N when N < 10. Without -s, columns are separated by\n\
1908 spaces. With no FILE, or when FILE is -, read standard input.\n\