1 /* pr -- convert text files for printing.
2 Copyright (C) 1988, 1991 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., 675 Mass Ave, Cambridge, MA 02139, 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. */
99 #include <sys/types.h>
108 static int char_to_clump ();
109 static int read_line ();
110 static int print_page ();
111 static int print_stored ();
112 static int open_file ();
113 static int skip_to_page ();
114 static void getoptarg ();
115 static void usage ();
116 static void print_files ();
117 static void init_header ();
118 static void init_store_cols ();
119 static void store_columns ();
120 static void balance ();
121 static void store_char ();
122 static void pad_down ();
123 static void read_rest_of_line ();
124 static void print_char ();
125 static void cleanup ();
132 /* Used with start_position in the struct COLUMN described below.
133 If start_position == ANYWHERE, we aren't truncating columns and
134 can begin printing a column anywhere. Otherwise we must pad to
135 the horizontal position start_position. */
138 /* Each column has one of these structures allocated for it.
139 If we're only dealing with one file, fp is the same for all
142 The general strategy is to spend time setting up these column
143 structures (storing columns if necessary), after which printing
144 is a matter of flitting from column to column and calling
147 Parallel files, single files printing across in multiple
148 columns, and single files printing down in multiple columns all
149 fit the same printing loop.
151 print_func Function used to print lines in this column.
152 If we're storing this column it will be
153 print_stored(), Otherwise it will be read_line().
155 char_func Function used to process characters in this column.
156 If we're storing this column it will be store_char(),
157 otherwise it will be print_char().
159 current_line Index of the current entry in line_vector, which
160 contains the index of the first character of the
161 current line in buff[].
163 lines_stored Number of lines in this column which are stored in
166 lines_to_print If we're storing this column, lines_to_print is
167 the number of stored_lines which remain to be
168 printed. Otherwise it is the number of lines
169 we can print without exceeding lines_per_body.
171 start_position The horizontal position we want to be in before we
172 print the first character in this column.
174 numbered True means precede this column with a line number. */
178 FILE *fp
; /* Input stream for this column. */
179 char *name
; /* File name. */
183 ON_HOLD
, /* Hit a form feed. */
185 } status
; /* Status of the file pointer. */
186 int (*print_func
) (); /* Func to print lines in this col. */
187 void (*char_func
) (); /* Func to print/store chars in this col. */
188 int current_line
; /* Index of current place in line_vector. */
189 int lines_stored
; /* Number of lines stored in buff. */
190 int lines_to_print
; /* No. lines stored or space left on page. */
191 int start_position
; /* Horizontal position of first char. */
195 typedef struct COLUMN COLUMN
;
197 #define NULLCOL (COLUMN *)0
199 /* The name under which this program was invoked. */
202 /* All of the columns to print. */
203 static COLUMN
*column_vector
;
205 /* When printing a single file in multiple downward columns,
206 we store the leftmost columns contiguously in buff.
207 To print a line from buff, get the index of the first char
208 from line_vector[i], and print up to line_vector[i + 1]. */
211 /* Index of the position in buff where the next character
213 static int buff_current
;
215 /* The number of characters in buff.
216 Used for allocation of buff and to detect overflow of buff. */
217 static int buff_allocated
;
219 /* Array of indices into buff.
220 Each entry is an index of the first character of a line.
221 This is used when storing lines to facilitate shuffling when
222 we do column balancing on the last page. */
223 static int *line_vector
;
225 /* Array of horizonal positions.
226 For each line in line_vector, end_vector[line] is the horizontal
227 position we are in after printing that line. We keep track of this
228 so that we know how much we need to pad to prepare for the next
230 static int *end_vector
;
232 /* (-m) True means we're printing multiple files in parallel. */
233 static int parallel_files
= FALSE
;
235 /* (-[0-9]+) True means we're given an option explicitly specifying
236 number of columns. Used to detect when this option is used with -m. */
237 static int explicit_columns
= FALSE
;
239 /* (-t) True means we're printing headers and footers. */
240 static int extremities
= TRUE
;
242 /* True means we need to print a header as soon as we know we've got input
243 to print after it. */
244 static int print_a_header
;
246 /* (-h) True means we're using the standard header rather than a
247 customized one specified by the -h flag. */
248 static int standard_header
= TRUE
;
250 /* (-f) True means use formfeeds instead of newlines to separate pages. */
251 static int use_form_feed
= FALSE
;
253 /* True means we have read the standard input. */
254 static int have_read_stdin
= FALSE
;
256 /* True means the -a flag has been given. */
257 static int print_across_flag
= FALSE
;
259 /* True means we're printing one file in multiple (>1) downward columns. */
260 static int storing_columns
= TRUE
;
262 /* (-b) True means balance columns on the last page as Sys V does. */
263 static int balance_columns
= FALSE
;
265 /* (-l) Number of lines on a page, including header and footer lines. */
266 static int lines_per_page
= 66;
268 /* Number of lines in the header and footer can be reset to 0 using
270 static int lines_per_header
= 5;
271 static int lines_per_body
;
272 static int lines_per_footer
= 5;
274 /* (-w) Width in characters of the page. Does not include the width of
276 static int chars_per_line
= 72;
278 /* Number of characters in a column. Based on the gutter and page widths. */
279 static int chars_per_column
;
281 /* (-e) True means convert tabs to spaces on input. */
282 static int untabify_input
= FALSE
;
284 /* (-e) The input tab character. */
285 static char input_tab_char
= '\t';
287 /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
288 where the leftmost column is 1. */
289 static int chars_per_input_tab
= 8;
291 /* (-i) True means convert spaces to tabs on output. */
292 static int tabify_output
= FALSE
;
294 /* (-i) The output tab character. */
295 static char output_tab_char
= '\t';
297 /* (-i) The width of the output tab. */
298 static int chars_per_output_tab
= 8;
300 /* Keeps track of pending white space. When we hit a nonspace
301 character after some whitespace, we print whitespace, tabbing
302 if necessary to get to output_position + spaces_not_printed. */
303 static int spaces_not_printed
;
305 /* Number of spaces between columns (though tabs can be used when possible to
306 use up the equivalent amount of space). Not sure if this is worth making
307 a flag for. BSD uses 0, Sys V uses 1. Sys V looks better. */
308 static int chars_per_gutter
= 1;
310 /* (-o) Number of spaces in the left margin (tabs used when possible). */
311 static int chars_per_margin
= 0;
313 /* Position where the next character will fall.
314 Leftmost position is 0 + chars_per_margin.
315 Rightmost position is chars_per_margin + chars_per_line - 1.
316 This is important for converting spaces to tabs on output. */
317 static int output_position
;
319 /* Horizontal position relative to the current file.
320 (output_position depends on where we are on the page;
321 input_position depends on where we are in the file.)
322 Important for converting tabs to spaces on input. */
323 static int input_position
;
325 /* Count number of failed opens so we can exit with non-zero
326 status if there were any. */
327 static int failed_opens
= 0;
329 /* The horizontal position we'll be at after printing a tab character
330 of width c_ from the position h_. */
331 #define pos_after_tab(c_, h_) h_ - h_ % c_ + c_
333 /* The number of spaces taken up if we print a tab character with width
334 c_ from position h_. */
335 #define tab_width(c_, h_) - h_ % c_ + c_
337 /* (-NNN) Number of columns of text to print. */
338 static int columns
= 1;
340 /* (+NNN) Page number on which to begin printing. */
341 static int first_page_number
= 1;
343 /* Number of files open (not closed, not on hold). */
344 static int files_ready_to_read
= 0;
346 /* Current page number. Displayed in header. */
347 static int page_number
;
349 /* Current line number. Displayed when -n flag is specified.
351 When printing files in parallel (-m flag), line numbering is as follows:
355 When printing files across (-a flag), ...
359 Otherwise, line numbering is as follows:
362 static int line_number
;
364 /* (-n) True means lines should be preceded by numbers. */
365 static int numbered_lines
= FALSE
;
367 /* (-n) Character which follows each line number. */
368 static char number_separator
= '\t';
370 /* (-n) Width in characters of a line number. */
371 static int chars_per_number
= 5;
373 /* Used when widening the first column to accommodate numbers -- only
374 needed when printing files in parallel. Includes width of both the
375 number and the number_separator. */
376 static int number_width
;
378 /* Buffer sprintf uses to format a line number. */
379 static char *number_buff
;
381 /* (-v) True means unprintable characters are printed as escape sequences.
382 control-g becomes \007. */
383 static int use_esc_sequence
= FALSE
;
385 /* (-c) True means unprintable characters are printed as control prefixes.
386 control-g becomes ^G. */
387 static int use_cntrl_prefix
= FALSE
;
389 /* (-d) True means output is double spaced. */
390 static int double_space
= FALSE
;
392 /* Number of files opened initially in init_files. Should be 1
393 unless we're printing multiple files in parallel. */
394 static int total_files
= 0;
396 /* (-r) True means don't complain if we can't open a file. */
397 static int ignore_failed_opens
= FALSE
;
399 /* (-s) True means we separate columns with a specified character. */
400 static int use_column_separator
= FALSE
;
402 /* Character used to separate columns if the the -s flag has been specified. */
403 static char column_separator
= '\t';
405 /* Number of separator characters waiting to be printed as soon as we
406 know that we have any input remaining to be printed. */
407 static int separators_not_printed
;
409 /* Position we need to pad to, as soon as we know that we have input
410 remaining to be printed. */
411 static int padding_not_printed
;
413 /* True means we should pad the end of the page. Remains false until we
414 know we have a page to print. */
415 static int pad_vertically
;
417 /* (-h) String of characters used in place of the filename in the header. */
418 static char *custom_header
;
420 /* String containing the date, filename or custom header, and "Page ". */
423 static int *clump_buff
;
425 /* True means we truncate lines longer than chars_per_column. */
426 static int truncate_lines
= FALSE
;
428 /* If non-zero, display usage information and exit. */
429 static int show_help
;
431 /* If non-zero, print the version on standard output then exit. */
432 static int show_version
;
434 static struct option
const long_options
[] =
436 {"help", no_argument
, &show_help
, 1},
437 {"version", no_argument
, &show_version
, 1},
441 /* Return the number of columns that have either an open file or
445 cols_ready_to_print ()
452 for (q
= column_vector
, i
= 0; i
< columns
; ++q
, ++i
)
453 if (q
->status
== OPEN
||
454 (storing_columns
&& q
->lines_stored
> 0 && q
->lines_to_print
> 0))
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
;
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 ("%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 (arg
, switch_char
, character
, number
)
673 char *arg
, switch_char
, *character
;
681 *number
= atoi (arg
);
685 %s: extra characters in the argument to the `-%c' option: `%s'\n",
686 program_name
, switch_char
, arg
);
692 /* Set parameters related to formatting. */
695 init_parameters (number_of_files
)
698 int chars_used_by_number
= 0;
700 lines_per_body
= lines_per_page
- lines_per_header
- lines_per_footer
;
701 if (lines_per_body
<= 0)
703 if (extremities
== FALSE
)
704 lines_per_body
= lines_per_page
;
707 lines_per_body
= lines_per_body
/ 2;
709 /* If input is stdin, cannot print parallel files. BSD dumps core
711 if (number_of_files
== 0)
712 parallel_files
= FALSE
;
715 columns
= number_of_files
;
717 /* Tabification is assumed for multiple columns. */
720 if (!use_column_separator
)
721 truncate_lines
= TRUE
;
723 untabify_input
= TRUE
;
724 tabify_output
= TRUE
;
727 storing_columns
= FALSE
;
731 if (number_separator
== input_tab_char
)
733 number_width
= chars_per_number
+
734 tab_width (chars_per_input_tab
,
735 (chars_per_margin
+ chars_per_number
));
738 number_width
= chars_per_number
+ 1;
739 /* The number is part of the column width unless we are
740 printing files in parallel. */
742 chars_used_by_number
= number_width
;
745 chars_per_column
= (chars_per_line
- chars_used_by_number
-
746 (columns
- 1) * chars_per_gutter
) / columns
;
748 if (chars_per_column
< 1)
749 error (1, 0, "page width too narrow");
753 if (number_buff
!= (char *) 0)
755 number_buff
= (char *)
756 xmalloc (2 * chars_per_number
* sizeof (char));
759 /* Pick the maximum between the tab width and the width of an
761 if (clump_buff
!= (int *) 0)
763 clump_buff
= (int *) xmalloc ((chars_per_input_tab
> 4
764 ? chars_per_input_tab
: 4) * sizeof (int));
767 /* Open the necessary files,
768 maintaining a COLUMN structure for each column.
770 With multiple files, each column p has a different p->fp.
771 With single files, each column p has the same p->fp.
772 Return 1 if (number_of_files > 0) and no files can be opened,
776 init_fps (number_of_files
, av
)
787 if (column_vector
!= NULLCOL
)
788 free ((char *) column_vector
);
789 column_vector
= (COLUMN
*) xmalloc (columns
* sizeof (COLUMN
));
793 files_left
= number_of_files
;
794 for (p
= column_vector
; files_left
--; ++p
, ++av
)
796 if (open_file (*av
, p
) == 0)
804 init_header ("", -1);
809 if (number_of_files
> 0)
811 if (open_file (*av
, p
) == 0)
813 init_header (*av
, fileno (p
->fp
));
817 p
->name
= "standard input";
819 have_read_stdin
= TRUE
;
822 init_header ("", -1);
827 for (i
= columns
- 1, ++p
; i
; --i
, ++p
)
834 files_ready_to_read
= total_files
;
838 /* Determine print_func and char_func, the functions
839 used by each column for printing and/or storing.
841 Determine the horizontal position desired when we begin
842 printing a column (p->start_position). */
850 h
= chars_per_margin
;
852 if (use_column_separator
)
856 /* When numbering lines of parallel files, we enlarge the
857 first column to accomodate the number. Looks better than
858 the Sys V approach. */
859 if (parallel_files
&& numbered_lines
)
860 h_next
= h
+ chars_per_column
+ number_width
;
862 h_next
= h
+ chars_per_column
;
865 /* This loop takes care of all but the rightmost column. */
867 for (p
= column_vector
, i
= 1; i
< columns
; ++p
, ++i
)
869 if (storing_columns
) /* One file, multi columns down. */
871 p
->char_func
= store_char
;
872 p
->print_func
= print_stored
;
875 /* One file, multi columns across; or parallel files. */
877 p
->char_func
= print_char
;
878 p
->print_func
= read_line
;
881 /* Number only the first column when printing files in
883 p
->numbered
= numbered_lines
&& (!parallel_files
|| i
== 1);
884 p
->start_position
= h
;
886 /* If we're using separators, all start_positions are
887 ANYWHERE, except the first column's start_position when
890 if (use_column_separator
)
897 h
= h_next
+ chars_per_gutter
;
898 h_next
= h
+ chars_per_column
;
902 /* The rightmost column.
904 Doesn't need to be stored unless we intend to balance
905 columns on the last page. */
906 if (storing_columns
&& balance_columns
)
908 p
->char_func
= store_char
;
909 p
->print_func
= print_stored
;
913 p
->char_func
= print_char
;
914 p
->print_func
= read_line
;
917 p
->numbered
= numbered_lines
&& (!parallel_files
|| i
== 1);
918 p
->start_position
= h
;
921 /* Open a file. Return nonzero if successful, zero if failed. */
928 if (!strcmp (name
, "-"))
930 p
->name
= "standard input";
937 p
->fp
= fopen (name
, "r");
942 if (!ignore_failed_opens
)
943 error (0, errno
, "%s", name
);
951 /* Close the file in P.
953 If we aren't dealing with multiple files in parallel, we change
954 the status of all columns in the column list to reflect the close. */
963 if (p
->status
== CLOSED
)
966 error (1, errno
, "%s", p
->name
);
967 if (p
->fp
!= stdin
&& fclose (p
->fp
) == EOF
)
968 error (1, errno
, "%s", p
->name
);
972 for (q
= column_vector
, i
= columns
; i
; ++q
, --i
)
975 if (q
->lines_stored
== 0)
977 q
->lines_to_print
= 0;
984 p
->lines_to_print
= 0;
987 --files_ready_to_read
;
990 /* Put a file on hold until we start a new page,
991 since we've hit a form feed.
993 If we aren't dealing with parallel files, we must change the
994 status of all columns in the column list. */
1003 if (!parallel_files
)
1004 for (q
= column_vector
, i
= columns
; i
; ++q
, --i
)
1005 q
->status
= ON_HOLD
;
1007 p
->status
= ON_HOLD
;
1008 p
->lines_to_print
= 0;
1009 --files_ready_to_read
;
1012 /* Undo hold_file -- go through the column list and change any
1013 ON_HOLD columns to OPEN. Used at the end of each page. */
1021 for (p
= column_vector
; i
; --i
, ++p
)
1022 if (p
->status
== ON_HOLD
)
1025 files_ready_to_read
++;
1029 /* Print a single file, or multiple files in parallel.
1031 Set up the list of columns, opening the necessary files.
1032 Allocate space for storing columns, if necessary.
1033 Skip to first_page_number, if user has asked to skip leading pages.
1034 Determine which functions are appropriate to store/print lines
1036 Print the file(s). */
1039 print_files (number_of_files
, av
)
1040 int number_of_files
;
1043 init_parameters (number_of_files
);
1044 if (init_fps (number_of_files
, av
))
1046 if (storing_columns
)
1049 if (first_page_number
> 1)
1051 if (!skip_to_page (first_page_number
))
1054 page_number
= first_page_number
;
1062 while (print_page ())
1066 /* Generous estimate of number of characters taken up by "Jun 7 00:08 " and
1068 #define CHARS_FOR_DATE_AND_PAGE 50
1070 /* Initialize header information.
1071 If DESC is non-negative, it is a file descriptor open to
1072 FILENAME for reading.
1074 Allocate space for a header string,
1075 Determine the time, insert file name or user-specified string.
1077 It might be nice to have a "blank headers" option, since
1078 pr -h "" still prints the date and page number. */
1081 init_header (filename
, desc
)
1085 int chars_per_header
;
1093 /* If parallel files or standard input, use current time. */
1094 if (desc
< 0 || !strcmp (filename
, "-") || fstat (desc
, &st
))
1095 st
.st_mtime
= time ((time_t *) 0);
1096 t
= ctime (&st
.st_mtime
);
1098 t
[16] = '\0'; /* Mark end of month and time string. */
1099 t
[24] = '\0'; /* Mark end of year string. */
1101 middle
= standard_header
? f
: custom_header
;
1103 chars_per_header
= strlen (middle
) + CHARS_FOR_DATE_AND_PAGE
+ 1;
1104 if (header
!= (char *) 0)
1106 header
= (char *) xmalloc (chars_per_header
* sizeof (char));
1108 sprintf (header
, "%s %s %s Page", &t
[4], &t
[20], middle
);
1111 /* Set things up for printing a page
1113 Scan through the columns ...
1114 Determine which are ready to print
1115 (i.e., which have lines stored or open files)
1116 Set p->lines_to_print appropriately
1117 (to p->lines_stored if we're storing, or lines_per_body
1118 if we're reading straight from the file)
1119 Keep track of this total so we know when to stop printing */
1127 if (storing_columns
)
1130 for (j
= columns
- 1, p
= column_vector
; j
; --j
, ++p
)
1132 p
->lines_to_print
= p
->lines_stored
;
1136 if (balance_columns
)
1138 p
->lines_to_print
= p
->lines_stored
;
1140 /* Since we're not balancing columns, we don't need to store
1141 the rightmost column. Read it straight from the file. */
1144 if (p
->status
== OPEN
)
1146 p
->lines_to_print
= lines_per_body
;
1149 p
->lines_to_print
= 0;
1153 for (j
= columns
, p
= column_vector
; j
; --j
, ++p
)
1154 if (p
->status
== OPEN
)
1156 p
->lines_to_print
= lines_per_body
;
1159 p
->lines_to_print
= 0;
1164 As long as there are lines left on the page and columns ready to print,
1165 Scan across the column list
1166 if the column has stored lines or the file is open
1167 pad to the appropriate spot
1169 pad the remainder of the page with \n or \f as requested
1170 reset the status of all files -- any files which where on hold because
1171 of formfeeds are now put back into the lineup. */
1177 int lines_left_on_page
;
1180 /* Used as an accumulator (with | operator) of successive values of
1181 pad_vertically. The trick is to set pad_vertically
1182 to zero before each run through the inner loop, then after that
1183 loop, it tells us whether a line was actually printed (whether a
1184 newline needs to be output -- or two for double spacing). But those
1185 values have to be accumulated (in pv) so we can invoke pad_down
1186 properly after the outer loop completes. */
1191 if (cols_ready_to_print () == 0)
1195 print_a_header
= TRUE
;
1197 /* Don't pad unless we know a page was printed. */
1198 pad_vertically
= FALSE
;
1201 lines_left_on_page
= lines_per_body
;
1203 lines_left_on_page
*= 2;
1205 while (lines_left_on_page
> 0 && cols_ready_to_print () > 0)
1207 output_position
= 0;
1208 spaces_not_printed
= 0;
1209 separators_not_printed
= 0;
1210 pad_vertically
= FALSE
;
1212 for (j
= 1, p
= column_vector
; j
<= columns
; ++j
, ++p
)
1215 if (p
->lines_to_print
> 0)
1217 padding_not_printed
= p
->start_position
;
1219 if (!(p
->print_func
) (p
))
1220 read_rest_of_line (p
);
1221 pv
|= pad_vertically
;
1223 if (use_column_separator
)
1224 ++separators_not_printed
;
1226 --p
->lines_to_print
;
1227 if (p
->lines_to_print
<= 0)
1229 if (cols_ready_to_print () <= 0)
1238 --lines_left_on_page
;
1241 if (double_space
&& pv
&& extremities
)
1244 --lines_left_on_page
;
1248 pad_vertically
= pv
;
1250 if (pad_vertically
&& extremities
)
1251 pad_down (lines_left_on_page
+ lines_per_footer
);
1253 reset_status (); /* Change ON_HOLD to OPEN. */
1255 return TRUE
; /* More pages to go. */
1258 /* Allocate space for storing columns.
1260 This is necessary when printing multiple columns from a single file.
1261 Lines are stored consecutively in buff, separated by '\0'.
1262 (We can't use a fixed offset since with the '-s' flag lines aren't
1265 We maintain a list (line_vector) of pointers to the beginnings
1266 of lines in buff. We allocate one more than the number of lines
1267 because the last entry tells us the index of the last character,
1268 which we need to know in order to print the last line in buff. */
1273 int total_lines
= lines_per_body
* columns
;
1274 int chars_if_truncate
= total_lines
* (chars_per_column
+ 1);
1276 if (line_vector
!= (int *) 0)
1277 free ((int *) line_vector
);
1278 line_vector
= (int *) xmalloc ((total_lines
+ 1) * sizeof (int *));
1280 if (end_vector
!= (int *) 0)
1281 free ((int *) end_vector
);
1282 end_vector
= (int *) xmalloc (total_lines
* sizeof (int *));
1284 if (buff
!= (char *) 0)
1286 buff_allocated
= use_column_separator
? 2 * chars_if_truncate
1287 : chars_if_truncate
; /* Tune this. */
1288 buff
= (char *) xmalloc (buff_allocated
* sizeof (char));
1291 /* Store all but the rightmost column.
1292 (Used when printing a single file in multiple downward columns)
1295 set p->current_line to be the index in line_vector of the
1296 first line in the column
1297 For each line in the column
1298 store the line in buff
1299 add to line_vector the index of the line's first char
1300 buff_start is the index in buff of the first character in the
1309 int last_col
; /* The rightmost column which will be saved in buff */
1315 if (balance_columns
)
1318 last_col
= columns
- 1;
1320 for (i
= 1, p
= column_vector
; i
<= last_col
; ++i
, ++p
)
1321 p
->lines_stored
= 0;
1323 for (i
= 1, p
= column_vector
; i
<= last_col
&& files_ready_to_read
;
1326 p
->current_line
= line
;
1327 for (j
= lines_per_body
; j
&& files_ready_to_read
; --j
)
1329 if (p
->status
== OPEN
) /* Redundant. Clean up. */
1333 if (!read_line (p
, i
))
1334 read_rest_of_line (p
);
1336 if (p
->status
== OPEN
1337 || buff_start
!= buff_current
)
1340 line_vector
[line
] = buff_start
;
1341 end_vector
[line
++] = input_position
;
1342 buff_start
= buff_current
;
1347 /* Keep track of the location of the last char in buff. */
1348 line_vector
[line
] = buff_start
;
1350 if (balance_columns
&& p
->lines_stored
!= lines_per_body
)
1355 balance (total_stored
)
1362 for (i
= 1, p
= column_vector
; i
<= columns
; ++i
, ++p
)
1364 lines
= total_stored
/ columns
;
1365 if (i
<= total_stored
% columns
)
1368 p
->lines_stored
= lines
;
1369 p
->current_line
= first_line
;
1371 first_line
+= lines
;
1375 /* Store a character in the buffer. */
1381 if (buff_current
>= buff_allocated
)
1383 /* May be too generous. */
1384 buff_allocated
= 2 * buff_allocated
;
1385 buff
= (char *) xrealloc (buff
, buff_allocated
* sizeof (char));
1387 buff
[buff_current
++] = (char) c
;
1397 sprintf (number_buff
, "%*d", chars_per_number
, line_number
++);
1399 for (i
= chars_per_number
; i
> 0; i
--)
1400 (p
->char_func
) ((int) *s
++);
1402 if (number_separator
== input_tab_char
)
1404 i
= number_width
- chars_per_number
;
1406 (p
->char_func
) ((int) ' ');
1409 (p
->char_func
) ((int) number_separator
);
1411 if (truncate_lines
&& !parallel_files
)
1412 input_position
+= number_width
;
1415 /* Print (or store) padding until the current horizontal position
1419 pad_across_to (position
)
1422 register int h
= output_position
;
1425 spaces_not_printed
= position
- output_position
;
1428 while (++h
<= position
)
1430 output_position
= position
;
1434 /* Pad to the bottom of the page.
1436 If the user has requested a formfeed, use one.
1437 Otherwise, use newlines. */
1448 for (i
= lines
; i
; --i
)
1452 /* Read the rest of the line.
1454 Read from the current column's file until an end of line is
1455 hit. Used when we've truncated a line and we no longer need
1456 to print or store its characters. */
1459 read_rest_of_line (p
)
1465 while ((c
= getc (f
)) != '\n')
1480 /* If we're tabifying output,
1482 When print_char encounters white space it keeps track
1483 of our desired horizontal position and delays printing
1484 until this function is called. */
1487 print_white_space ()
1490 register int h_old
= output_position
;
1491 register int goal
= h_old
+ spaces_not_printed
;
1493 while (goal
- h_old
> 1
1494 && (h_new
= pos_after_tab (chars_per_output_tab
, h_old
)) <= goal
)
1496 putchar (output_tab_char
);
1499 while (++h_old
<= goal
)
1502 output_position
= goal
;
1503 spaces_not_printed
= 0;
1506 /* Print column separators.
1508 We keep a count until we know that we'll be printing a line,
1509 then print_separators() is called. */
1514 for (; separators_not_printed
> 0; --separators_not_printed
)
1515 print_char (column_separator
);
1518 /* Print (or store, depending on p->char_func) a clump of N
1522 print_clump (p
, n
, clump
)
1528 (p
->char_func
) (*clump
++);
1531 /* Print a character.
1533 If we're tabifying, all tabs have been converted to spaces by
1534 process_char(). Keep a count of consecutive spaces, and when
1535 a nonspace is encountered, call print_white_space() to print the
1536 required number of tabs and spaces. */
1546 ++spaces_not_printed
;
1549 else if (spaces_not_printed
> 0)
1550 print_white_space ();
1552 /* Nonprintables are assumed to have width 0, except '\b'. */
1564 /* Skip to page PAGE before printing. */
1573 for (n
= 1; n
< page
; ++n
)
1575 for (i
= 1; i
<= lines_per_body
; ++i
)
1577 for (j
= 1, p
= column_vector
; j
<= columns
; ++j
, ++p
)
1578 read_rest_of_line (p
);
1582 return files_ready_to_read
> 0;
1587 Formfeeds are assumed to use up two lines at the beginning of
1594 fprintf (stdout
, "\n\n");
1596 output_position
= 0;
1597 pad_across_to (chars_per_margin
);
1598 print_white_space ();
1600 fprintf (stdout
, "%s %d\n\n\n", header
, page_number
++);
1602 print_a_header
= FALSE
;
1603 output_position
= 0;
1606 /* Print (or store, if p->char_func is store_char()) a line.
1608 Read a character to determine whether we have a line or not.
1609 (We may hit EOF, \n, or \f)
1611 Once we know we have a line,
1612 set pad_vertically = TRUE, meaning it's safe
1613 to pad down at the end of the page, since we do have a page.
1614 print a header if needed.
1615 pad across to padding_not_printed if needed.
1616 print any separators which need to be printed.
1617 print a line number if it needs to be printed.
1619 Print the clump which corresponds to the first character.
1621 Enter a loop and keep printing until an end of line condition
1622 exists, or until we exceed chars_per_column.
1624 Return FALSE if we exceed chars_per_column before reading
1625 an end of line character, TRUE otherwise. */
1631 register int c
, chars
;
1632 int last_input_position
;
1636 last_input_position
= input_position
;
1648 chars
= char_to_clump (c
);
1651 if (truncate_lines
&& input_position
> chars_per_column
)
1653 input_position
= last_input_position
;
1657 if (p
->char_func
!= store_char
)
1659 pad_vertically
= TRUE
;
1664 if (padding_not_printed
!= ANYWHERE
)
1666 pad_across_to (padding_not_printed
);
1667 padding_not_printed
= ANYWHERE
;
1670 if (use_column_separator
)
1671 print_separators ();
1680 print_clump (p
, chars
, clump_buff
);
1698 last_input_position
= input_position
;
1699 chars
= char_to_clump (c
);
1700 if (truncate_lines
&& input_position
> chars_per_column
)
1702 input_position
= last_input_position
;
1706 print_clump (p
, chars
, clump_buff
);
1710 /* Print a line from buff.
1712 If this function has been called, we know we have something to
1713 print. Therefore we set pad_vertically to TRUE, print
1714 a header if necessary, pad across if necessary, and print
1715 separators if necessary.
1717 Return TRUE, meaning there is no need to call read_rest_of_line. */
1723 int line
= p
->current_line
++;
1724 register char *first
= &buff
[line_vector
[line
]];
1725 register char *last
= &buff
[line_vector
[line
+ 1]];
1727 pad_vertically
= TRUE
;
1732 if (padding_not_printed
!= ANYWHERE
)
1734 pad_across_to (padding_not_printed
);
1735 padding_not_printed
= ANYWHERE
;
1738 if (use_column_separator
)
1739 print_separators ();
1741 while (first
!= last
)
1742 print_char (*first
++);
1744 if (spaces_not_printed
== 0)
1745 output_position
= p
->start_position
+ end_vector
[line
];
1750 /* Convert a character to the proper format and return the number of
1751 characters in the resulting clump. Increment input_position by
1752 the width of the clump.
1754 Tabs are converted to clumps of spaces.
1755 Nonprintable characters may be converted to clumps of escape
1756 sequences or control prefixes.
1758 Note: the width of a clump is not necessarily equal to the number of
1759 characters in clump_buff. (e.g, the width of '\b' is -1, while the
1760 number of characters is 1.) */
1766 register int *s
= clump_buff
;
1772 if (c
== input_tab_char
)
1774 width
= tab_width (chars_per_input_tab
, input_position
);
1778 for (i
= width
; i
; --i
)
1789 else if (!ISPRINT (c
))
1791 if (use_esc_sequence
)
1796 sprintf (esc_buff
, "%03o", c
);
1797 for (i
= 0; i
<= 2; ++i
)
1798 *s
++ = (int) esc_buff
[i
];
1800 else if (use_cntrl_prefix
)
1814 sprintf (esc_buff
, "%03o", c
);
1815 for (i
= 0; i
<= 2; ++i
)
1816 *s
++ = (int) esc_buff
[i
];
1839 input_position
+= width
;
1843 /* We've just printed some files and need to clean up things before
1844 looking for more options and printing the next batch of files.
1846 Free everything we've xmalloc'ed, except `header'. */
1856 free (column_vector
);
1865 /* Complain, print a usage message, and die. */
1871 Usage: %s [+PAGE] [-COLUMN] [-abcdfFmrtv] [-e[in-tab-char[in-tab-width]]]\n\
1872 [-h header] [-i[out-tab-char[out-tab-width]]] [-l page-length]\n\
1873 [-n[number-separator[digits]]] [-o left-margin]\n\
1874 [-s[column-separator]] [-w page-width] [--help] [--version] [file...]\n",