*** empty log message ***
[coreutils.git] / src / pr.c
blob161d205f5083dc13083ce40228c471d68da80f40
1 /* pr -- convert text files for printing.
2 Copyright (C) 88, 91, 95, 96, 1997 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Author: Pete TerMaat. */
20 /* Things to watch: Sys V screws up on ...
21 pr -n -3 -s: /usr/dict/words
22 pr -m -o10 -n /usr/dict/words{,,,}
23 pr -6 -a -n -o5 /usr/dict/words
25 Ideas:
27 Keep a things_to_do list of functions to call when we know we have
28 something to print. Cleaner than current series of checks.
30 Improve the printing of control prefixes.
33 Options:
35 +FIRST_PAGE[:LAST_PAGE]
36 begin [stop] printing with page FIRST_[LAST_]PAGE
38 -COLUMN Produce output that is COLUMN columns wide and print
39 columns down.
40 Balance columns on the last page is automatically set.
42 -a Print columns across rather than down. The input
43 one
44 two
45 three
46 four
47 will be printed as
48 one two three
49 four
51 -b Balance columns on the last page.
52 -b is no longer an independent option. It's always used
53 together with -COLUMN (unless -a is used) to get a
54 consistent formulation with "FF set by hand" in input
55 files. Each formfeed found terminates the number of lines
56 to be read with the actual page. The situation for
57 printing columns down is equivalent to that on the last
58 page. So we need a balancing.
60 We do not yet eliminate source text dealing with -COLUMN
61 only. Tune this if it proved to be a satisfactory
62 procedure.
64 Keeping -b as an underground option guarantees some
65 downward compatibility. Utilities using pr with -b
66 (a most frequently used form) still work as usual.
68 -c Print unprintable characters as control prefixes.
69 Control-g is printed as ^G.
71 -d Double space the output.
73 -e[c[k]] Expand tabs to spaces on input. Optional argument C
74 is the input tab character. (Default is `\t'.) Optional
75 argument K is the input tab character's width. (Default is 8.)
78 -f Use formfeeds instead of newlines to separate pages.
79 A three line HEADER is used, no TRAILER (without -f
80 both HEADER and TRAILER are made of five lines).
82 -h HEADER Replace the filename in the header with the string HEADER.
83 Checking and left-hand-side truncation of the length of the
84 standard and custom header string. A centered header is used.
85 The format of date and time has been shortened
86 to yy-mm-dd HH:MM to give place to a maximal filename
87 information.
88 -h "" now prints a blank line header. -h"" shows an error.
90 -i[c[k]] Replace spaces with tabs on output. Optional argument
91 C is the output tab character. (Default is `\t'.) Optional
92 argument K is the output tab character's width. (Default
93 is 8.)
95 -j Merge full lines, turns off -w line truncation, no column
96 alignment, -s[STRING] sets separators, works with all
97 column options (-COLUMN | -a -COLUMN | -m).
99 -l lines Set the page length to LINES. Default is 66.
101 -m Print files in parallel; pad_across_to align columns;
102 truncate lines and print separator strings;
103 Do it also with empty columns to get a continuous line
104 numbering and column marking by separators throughout
105 the whole merged file.
107 Empty pages in some input files produce empty columns
108 [marked by separators] in the common pages. Completely
109 empty common pages show no column separators at all.
111 The layout of a merged page is ruled by the largest form
112 feed distance of the single pages at that page. Shorter
113 columns will be filled up with empty lines.
115 Together with -j option join lines of full length and
116 in addition set separators when -s option is used.
118 -n[c[k]] Precede each column with a line number.
119 (With parallel files, precede each line with a line
120 number.) Optional argument C is the character to print
121 after each number. (Default `\t'.) Optional argument
122 k is the number of digits per line number. (Default 5.)
123 Default counting starts with 1st line of input file.
125 -N number Start counting with number at 1st line of first page
126 printed.
128 -o offset Offset each line with a margin OFFSET spaces wide.
129 Total page width is the size of this offset plus the
130 width set with `-w'.
132 -r Ignore files that can't be opened.
134 -s[STRING] Separate columns by any string STRING.
135 Don't use -s "STRING".
136 without -s: Default separator `TAB' with -j and `space'
137 otherwise (same as -s\" \"),
138 with -s only: no separator is used, same as -s"".
139 Quotes should be used with blanks and some shell active
140 characters.
142 -t Do not print headers or footers but retain form feeds
143 set in input files (some page layout is not changed).
145 -T Do not print headers or footers, eliminate form feeds
146 in input files.
148 -v Print unprintable characters as escape sequences.
149 Control-G becomes \007.
151 -w width Set the page width to WIDTH characters.
152 (In pr versions newer than 1.14 -s option does no longer
153 affect -w option.)
155 With/without -w width the header line is truncated.
156 Default is 72 characters.
157 With -w width text lines will be truncated, unless -j is
158 used. Together with one of the column options
159 (-COLUMN| -a -COLUMN| -m) column alignment is used.
160 Without -w PAGE_WIDTH
161 - but with one of the column options default truncation of
162 72 characters is used (to keep downward compatibility
163 and to simplify most frequently met column tasks).
164 Column alignment and column separators are used.
165 - and without any of the column options no line truncation
166 is used (to keep downward compatibility and to meet most
167 frequent tasks). That's equivalent to -w 72 -j .
171 #include <config.h>
173 #include <stdio.h>
174 #include <getopt.h>
175 #include <sys/types.h>
176 #include <time.h>
177 #include "system.h"
178 #include "error.h"
179 #include "xstrtol.h"
181 #if HAVE_LIMITS_H
182 # include <limits.h>
183 #endif
185 char *xmalloc ();
186 char *xrealloc ();
188 #ifndef UINT_MAX
189 # define UINT_MAX ((unsigned int) ~(unsigned int) 0)
190 #endif
192 #ifndef INT_MAX
193 # define INT_MAX ((int) (UINT_MAX >> 1))
194 #endif
196 #ifndef TRUE
197 # define TRUE 1
198 # define FALSE 0
199 #endif
201 /* Used with start_position in the struct COLUMN described below.
202 If start_position == ANYWHERE, we aren't truncating columns and
203 can begin printing a column anywhere. Otherwise we must pad to
204 the horizontal position start_position. */
205 #define ANYWHERE 0
207 /* Each column has one of these structures allocated for it.
208 If we're only dealing with one file, fp is the same for all
209 columns.
211 The general strategy is to spend time setting up these column
212 structures (storing columns if necessary), after which printing
213 is a matter of flitting from column to column and calling
214 print_func.
216 Parallel files, single files printing across in multiple
217 columns, and single files printing down in multiple columns all
218 fit the same printing loop.
220 print_func Function used to print lines in this column.
221 If we're storing this column it will be
222 print_stored(), Otherwise it will be read_line().
224 char_func Function used to process characters in this column.
225 If we're storing this column it will be store_char(),
226 otherwise it will be print_char().
228 current_line Index of the current entry in line_vector, which
229 contains the index of the first character of the
230 current line in buff[].
232 lines_stored Number of lines in this column which are stored in
233 buff.
235 lines_to_print If we're storing this column, lines_to_print is
236 the number of stored_lines which remain to be
237 printed. Otherwise it is the number of lines
238 we can print without exceeding lines_per_body.
240 start_position The horizontal position we want to be in before we
241 print the first character in this column.
243 numbered True means precede this column with a line number. */
245 struct COLUMN
247 FILE *fp; /* Input stream for this column. */
248 char *name; /* File name. */
249 enum
251 OPEN,
252 FF_FOUND, /* used with -b option, set with \f, changed
253 to ON_HOLD after print_header */
254 ON_HOLD, /* Hit a form feed. */
255 CLOSED
257 status; /* Status of the file pointer. */
258 int (*print_func) (); /* Func to print lines in this col. */
259 void (*char_func) (); /* Func to print/store chars in this col. */
260 int current_line; /* Index of current place in line_vector. */
261 int lines_stored; /* Number of lines stored in buff. */
262 int lines_to_print; /* No. lines stored or space left on page. */
263 int start_position; /* Horizontal position of first char. */
264 int numbered;
265 int full_page_printed; /* True means printed without a FF found. */
267 /* p->full_page_printed controls a special case of "FF set by hand":
268 True means a full page has been printed without FF found. To avoid an
269 additional empty page we have to ignore a FF immediately following in
270 the next line. */
273 typedef struct COLUMN COLUMN;
275 #define NULLCOL (COLUMN *)0
277 static int char_to_clump __P ((int c));
278 static int read_line __P ((COLUMN *p));
279 static int print_page __P ((void));
280 static int print_stored __P ((COLUMN *p));
281 static int open_file __P ((char *name, COLUMN *p));
282 static int skip_to_page __P ((int page));
283 static void print_header __P ((void));
284 static void pad_across_to __P ((int position));
285 static void add_line_number __P ((COLUMN *p));
286 static void getoptarg __P ((char *arg, char switch_char, char *character,
287 int *number));
288 static void usage __P ((int status));
289 static void print_files __P ((int number_of_files, char **av));
290 static void init_parameters __P ((int number_of_files));
291 static void init_header __P ((char *filename, int desc));
292 static void init_store_cols __P ((void));
293 static void store_columns __P ((void));
294 static void balance __P ((int total_stored));
295 static void store_char __P ((int c));
296 static void pad_down __P ((int lines));
297 static void read_rest_of_line __P ((COLUMN *p));
298 static void skip_read __P ((COLUMN *p, int column_number));
299 static void print_char __P ((int c));
300 static void cleanup __P ((void));
301 static void first_last_page __P ((char *pages));
302 static void print_sep_string __P ((void));
303 static void separator_string __P ((const char *optarg_S));
305 /* The name under which this program was invoked. */
306 char *program_name;
308 /* All of the columns to print. */
309 static COLUMN *column_vector;
311 /* When printing a single file in multiple downward columns,
312 we store the leftmost columns contiguously in buff.
313 To print a line from buff, get the index of the first character
314 from line_vector[i], and print up to line_vector[i + 1]. */
315 static char *buff;
317 /* Index of the position in buff where the next character
318 will be stored. */
319 static int buff_current;
321 /* The number of characters in buff.
322 Used for allocation of buff and to detect overflow of buff. */
323 static int buff_allocated;
325 /* Array of indices into buff.
326 Each entry is an index of the first character of a line.
327 This is used when storing lines to facilitate shuffling when
328 we do column balancing on the last page. */
329 static int *line_vector;
331 /* Array of horizonal positions.
332 For each line in line_vector, end_vector[line] is the horizontal
333 position we are in after printing that line. We keep track of this
334 so that we know how much we need to pad to prepare for the next
335 column. */
336 static int *end_vector;
338 /* (-m) True means we're printing multiple files in parallel. */
339 static int parallel_files = FALSE;
341 /* (-m) True means a line starts with some empty columns (some files
342 already CLOSED or ON_HOLD) which we have to align. */
343 static int align_empty_cols;
345 /* (-m) True means we have not yet found any printable column in a line.
346 align_empty_cols = TRUE has to be maintained. */
347 static int empty_line;
349 /* (-m) False means printable column output precedes a form feed found.
350 Column align is done only once. No additional action with that form
351 feed.
352 True means we found only a form feed in a column. Maybe we have to do
353 some column align with that form feed. */
354 static int FF_only;
356 /* (-[0-9]+) True means we're given an option explicitly specifying
357 number of columns. Used to detect when this option is used with -m. */
358 static int explicit_columns = FALSE;
360 /* (-t|-T) False means we aren't printing headers and footers. */
361 static int extremities = TRUE;
363 /* (-t) True means we retain all FF set by hand in input files.
364 False is set with -T option. */
365 static int keep_FF = FALSE;
366 static int print_a_FF = FALSE;
368 /* True means we need to print a header as soon as we know we've got input
369 to print after it. */
370 static int print_a_header;
372 /* (-h) True means we're using the standard header rather than a
373 customized one specified by the -h flag. */
374 static int standard_header = TRUE;
376 /* (-f) True means use formfeeds instead of newlines to separate pages. */
377 static int use_form_feed = FALSE;
379 /* True means we have read the standard input. */
380 static int have_read_stdin = FALSE;
382 /* True means the -a flag has been given. */
383 static int print_across_flag = FALSE;
385 /* True means we're printing one file in multiple (>1) downward columns. */
386 static int storing_columns = TRUE;
388 /* (-b) True means balance columns on the last page as Sys V does. */
389 /* That's no longer an independent option. With storing_columns = TRUE
390 balance_columns = TRUE is used too (s. function init_parameters).
391 We get a consistent formulation with "FF set by hand" in input files. */
392 static int balance_columns = FALSE;
394 /* (-l) Number of lines on a page, including header and footer lines. */
395 static int lines_per_page = 66;
397 /* Number of lines in the header and footer can be reset to 0 using
398 the -t flag. */
399 static int lines_per_header = 5;
400 static int lines_per_body;
401 static int lines_per_footer = 5;
403 /* (-w) Width in characters of the page. Does not include the width of
404 the margin. */
405 static int chars_per_line = 72;
407 /* (-w) True means we truncate lines longer than chars_per_column. */
408 static int truncate_lines = FALSE;
410 /* (-j) True means we join lines without any line truncation. -j
411 dominates -w option. */
412 static int join_lines = FALSE;
414 /* Number of characters in a column. Based on col_sep_length and
415 page width. */
416 static int chars_per_column;
418 /* (-e) True means convert tabs to spaces on input. */
419 static int untabify_input = FALSE;
421 /* (-e) The input tab character. */
422 static char input_tab_char = '\t';
424 /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
425 where the leftmost column is 1. */
426 static int chars_per_input_tab = 8;
428 /* (-i) True means convert spaces to tabs on output. */
429 static int tabify_output = FALSE;
431 /* (-i) The output tab character. */
432 static char output_tab_char = '\t';
434 /* (-i) The width of the output tab. */
435 static int chars_per_output_tab = 8;
437 /* Keeps track of pending white space. When we hit a nonspace
438 character after some whitespace, we print whitespace, tabbing
439 if necessary to get to output_position + spaces_not_printed. */
440 static int spaces_not_printed;
442 /* (-o) Number of spaces in the left margin (tabs used when possible). */
443 static int chars_per_margin = 0;
445 /* Position where the next character will fall.
446 Leftmost position is 0 + chars_per_margin.
447 Rightmost position is chars_per_margin + chars_per_line - 1.
448 This is important for converting spaces to tabs on output. */
449 static int output_position;
451 /* Horizontal position relative to the current file.
452 (output_position depends on where we are on the page;
453 input_position depends on where we are in the file.)
454 Important for converting tabs to spaces on input. */
455 static int input_position;
457 /* Count number of failed opens so we can exit with nonzero
458 status if there were any. */
459 static int failed_opens = 0;
461 /* The number of spaces taken up if we print a tab character with width
462 c_ from position h_. */
463 #define TAB_WIDTH(c_, h_) ((c_) - ((h_) % (c_)))
465 /* The horizontal position we'll be at after printing a tab character
466 of width c_ from the position h_. */
467 #define POS_AFTER_TAB(c_, h_) ((h_) + TAB_WIDTH (c_, h_))
469 /* (-NNN) Number of columns of text to print. */
470 static int columns = 1;
472 /* (+NNN:MMM) Page numbers on which to begin and stop printing. */
473 static int first_page_number = 1;
474 static int last_page_number = 0;
476 /* Number of files open (not closed, not on hold). */
477 static int files_ready_to_read = 0;
479 /* Current page number. Displayed in header. */
480 static int page_number;
482 /* Current line number. Displayed when -n flag is specified.
484 When printing files in parallel (-m flag), line numbering is as follows:
485 1 foo goo moo
486 2 hoo too zoo
488 When printing files across (-a flag), ...
489 1 foo 2 moo 3 goo
490 4 hoo 3 too 6 zoo
492 Otherwise, line numbering is as follows:
493 1 foo 3 goo 5 too
494 2 moo 4 hoo 6 zoo */
495 static int line_number;
497 /* (-n) True means lines should be preceded by numbers. */
498 static int numbered_lines = FALSE;
500 /* (-n) Character which follows each line number. */
501 static char number_separator = '\t';
503 /* (-n) line counting starts with 1st line of input file (not with 1st
504 line of 1st page printed). */
505 static int line_count = 1;
507 /* (-n) True means counting of skipped lines starts with 1st line of
508 input file. False means -N option is used in addition, counting of
509 skipped lines not required. */
510 static int skip_count = TRUE;
512 /* (-N) Counting starts with start_line_number = NUMBER at 1st line of
513 first page printed, usually not 1st page of input file. */
514 static int start_line_num = 1;
516 /* (-n) Width in characters of a line number. */
517 static int chars_per_number = 5;
519 /* Used when widening the first column to accommodate numbers -- only
520 needed when printing files in parallel. Includes width of both the
521 number and the number_separator. */
522 static int number_width;
524 /* Buffer sprintf uses to format a line number. */
525 static char *number_buff;
527 /* (-v) True means unprintable characters are printed as escape sequences.
528 control-g becomes \007. */
529 static int use_esc_sequence = FALSE;
531 /* (-c) True means unprintable characters are printed as control prefixes.
532 control-g becomes ^G. */
533 static int use_cntrl_prefix = FALSE;
535 /* (-d) True means output is double spaced. */
536 static int double_space = FALSE;
538 /* Number of files opened initially in init_files. Should be 1
539 unless we're printing multiple files in parallel. */
540 static int total_files = 0;
542 /* (-r) True means don't complain if we can't open a file. */
543 static int ignore_failed_opens = FALSE;
545 /* (-s) True means we separate columns with a specified string.
546 -s option does not affect line truncation nor column alignment. */
547 static int use_col_separator = FALSE;
549 /* String used to separate columns if the -s option has been specified.
550 Default without -s but together with one of the column options
551 -a|COLUMN|-m is a `space' and with the -j option a `tab'. */
552 static char *col_sep_string;
553 static int col_sep_length = 0;
554 static char *column_separator = " ";
555 static char *line_separator = "\t";
557 /* Number of separator characters waiting to be printed as soon as we
558 know that we have any input remaining to be printed. */
559 static int separators_not_printed;
561 /* Position we need to pad to, as soon as we know that we have input
562 remaining to be printed. */
563 static int padding_not_printed;
565 /* True means we should pad the end of the page. Remains false until we
566 know we have a page to print. */
567 static int pad_vertically;
569 /* (-h) String of characters used in place of the filename in the header. */
570 static char *custom_header;
572 /* String containing the date, filename or custom header, and "Page ". */
573 static char *header;
575 static int *clump_buff;
577 /* If nonzero, display usage information and exit. */
578 static int show_help;
580 /* If nonzero, print the version on standard output then exit. */
581 static int show_version;
583 /* True means we read the line no. lines_per_body in skip_read
584 called by skip_to_page. That variable controls the coincidence of a
585 "FF set by hand" and "full_page_printed", see above the definition of
586 structure COLUMN. */
587 static int last_line = FALSE;
589 /* If nonzero, print a non-variable date and time with the header
590 -h HEADER using pr test-suite */
591 static int test_suite;
593 static struct option const long_options[] =
595 {"help", no_argument, &show_help, 1},
596 {"version", no_argument, &show_version, 1},
597 {"test", no_argument, &test_suite, 1},
598 {0, 0, 0, 0}
601 /* Return the number of columns that have either an open file or
602 stored lines. */
604 static int
605 cols_ready_to_print (void)
607 COLUMN *q;
608 int i;
609 int n;
611 n = 0;
612 for (q = column_vector, i = 0; i < columns; ++q, ++i)
613 if (q->status == OPEN ||
614 q->status == FF_FOUND || /* With -b: To print a header only */
615 (storing_columns && q->lines_stored > 0 && q->lines_to_print > 0))
616 ++n;
617 return n;
620 /* Estimate first_ / last_page_number
621 using option +FIRST_PAGE:LAST_PAGE */
623 static void
624 first_last_page (char *pages)
626 char *str1;
628 if (*pages == ':')
630 error (0, 0, _("invalid range of page numbers: `%s'"), pages);
631 usage (2);
634 str1 = strchr (pages, ':');
635 if (str1 != NULL)
636 *str1 = '\0';
639 long int tmp_long;
640 if (xstrtol (pages, NULL, 10, &tmp_long, "") != LONGINT_OK
641 || tmp_long <= 0 || tmp_long > INT_MAX)
642 error (EXIT_FAILURE, 0, _("invalid starting page number: `%s'"),
643 pages);
644 first_page_number = (int) tmp_long;
647 if (str1 == NULL)
648 return;
651 long int tmp_long;
652 if (xstrtol (str1 + 1, NULL, 10, &tmp_long, "") != LONGINT_OK
653 || tmp_long <= 0 || tmp_long > INT_MAX)
654 error (EXIT_FAILURE, 0, _("invalid ending page number: `%s'"),
655 str1 + 1);
656 last_page_number = (int) tmp_long;
659 if (first_page_number > last_page_number)
660 error (EXIT_FAILURE, 0,
661 _("starting page number is larger than ending page number"));
664 /* Estimate length of col_sep_string with option -s[STRING] */
666 static void
667 separator_string (const char *optarg_S)
669 col_sep_length = (int) strlen (optarg_S);
670 col_sep_string = (char *) xmalloc (col_sep_length + 1);
671 strcpy (col_sep_string, optarg_S);
675 main (int argc, char **argv)
677 int c;
678 int accum = 0;
679 int n_files;
680 char **file_names;
682 program_name = argv[0];
683 setlocale (LC_ALL, "");
684 bindtextdomain (PACKAGE, LOCALEDIR);
685 textdomain (PACKAGE);
687 n_files = 0;
688 file_names = (argc > 1
689 ? (char **) xmalloc ((argc - 1) * sizeof (char *))
690 : NULL);
692 while (1)
694 c = getopt_long (argc, argv,
695 "-0123456789abcde::fFh:i::jl:mn::N:o:rs::tTvw:",
696 long_options, NULL);
697 if (c == 1) /* Non-option argument. */
699 char *s;
700 s = optarg;
701 if (*s == '+')
703 ++s;
704 first_last_page (s);
706 else
708 file_names[n_files++] = optarg;
711 else
713 if (ISDIGIT (c))
715 accum = accum * 10 + c - '0';
716 continue;
718 else
720 if (accum > 0)
722 columns = accum;
723 explicit_columns = TRUE;
724 accum = 0;
729 if (c == 1)
730 continue;
732 if (c == EOF)
733 break;
735 switch (c)
737 case 0: /* getopt long option */
738 break;
740 case 'a':
741 print_across_flag = TRUE;
742 storing_columns = FALSE;
743 break;
744 case 'b':
745 balance_columns = TRUE;
746 break;
747 case 'c':
748 use_cntrl_prefix = TRUE;
749 break;
750 case 'd':
751 double_space = TRUE;
752 break;
753 case 'e':
754 if (optarg)
755 getoptarg (optarg, 'e', &input_tab_char,
756 &chars_per_input_tab);
757 /* Could check tab width > 0. */
758 untabify_input = TRUE;
759 break;
760 case 'f':
761 case 'F':
762 use_form_feed = TRUE;
763 break;
764 case 'h':
765 custom_header = optarg;
766 standard_header = FALSE;
767 break;
768 case 'i':
769 if (optarg)
770 getoptarg (optarg, 'i', &output_tab_char,
771 &chars_per_output_tab);
772 /* Could check tab width > 0. */
773 tabify_output = TRUE;
774 break;
775 case 'j':
776 join_lines = TRUE;
777 break;
778 case 'l':
780 long int tmp_long;
781 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
782 || tmp_long <= 0 || tmp_long > INT_MAX)
784 error (EXIT_FAILURE, 0,
785 _("`-l PAGE_LENGTH' invalid number of lines: `%s'"),
786 optarg);
788 lines_per_page = (int) tmp_long;
789 break;
791 case 'm':
792 parallel_files = TRUE;
793 storing_columns = FALSE;
794 break;
795 case 'n':
796 numbered_lines = TRUE;
797 if (optarg)
798 getoptarg (optarg, 'n', &number_separator,
799 &chars_per_number);
800 break;
801 case 'N':
802 skip_count = FALSE;
804 long int tmp_long;
805 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
806 || tmp_long > INT_MAX)
808 error (EXIT_FAILURE, 0,
809 _("`-N NUMBER' invalid starting line number: `%s'"),
810 optarg);
812 start_line_num = (int) tmp_long;
813 break;
815 case 'o':
817 long int tmp_long;
818 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
819 || tmp_long < 0 || tmp_long > INT_MAX)
820 error (EXIT_FAILURE, 0,
821 _("`-o MARGIN' invalid line offset: `%s'"), optarg);
822 chars_per_margin = (int) tmp_long;
823 break;
825 case 'r':
826 ignore_failed_opens = TRUE;
827 break;
828 case 's':
829 use_col_separator = TRUE;
830 if (optarg)
831 separator_string (optarg);
832 break;
833 case 't':
834 extremities = FALSE;
835 keep_FF = TRUE;
836 break;
837 case 'T':
838 extremities = FALSE;
839 keep_FF = FALSE;
840 break;
841 case 'v':
842 use_esc_sequence = TRUE;
843 break;
844 case 'w':
845 truncate_lines = TRUE;
847 long int tmp_long;
848 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
849 || tmp_long <= 0 || tmp_long > INT_MAX)
850 error (EXIT_FAILURE, 0,
851 _("`-w PAGE_WIDTH' invalid column number: `%s'"), optarg);
852 chars_per_line = (int) tmp_long;
853 break;
855 default:
856 usage (2);
857 break;
861 if (show_version)
863 printf ("pr (%s) %s\n", GNU_PACKAGE, VERSION);
864 exit (EXIT_SUCCESS);
867 if (show_help)
868 usage (0);
870 if (parallel_files && explicit_columns)
871 error (EXIT_FAILURE, 0,
872 _("Cannot specify number of columns when printing in parallel."));
874 if (parallel_files && print_across_flag)
875 error (EXIT_FAILURE, 0,
876 _("Cannot specify both printing across and printing in parallel."));
878 for (; optind < argc; optind++)
880 file_names[n_files++] = argv[optind];
883 if (n_files == 0)
885 /* No file arguments specified; read from standard input. */
886 print_files (0, NULL);
888 else
890 if (parallel_files)
891 print_files (n_files, file_names);
892 else
894 int i;
895 for (i = 0; i < n_files; i++)
896 print_files (1, &file_names[i]);
900 cleanup ();
902 if (have_read_stdin && fclose (stdin) == EOF)
903 error (EXIT_FAILURE, errno, _("standard input"));
904 if (ferror (stdout) || fclose (stdout) == EOF)
905 error (EXIT_FAILURE, errno, _("write error"));
906 if (failed_opens > 0)
907 exit (EXIT_FAILURE);
908 exit (EXIT_SUCCESS);
911 /* Parse options of the form -scNNN.
913 Example: -nck, where 'n' is the option, c is the optional number
914 separator, and k is the optional width of the field used when printing
915 a number. */
917 static void
918 getoptarg (char *arg, char switch_char, char *character, int *number)
920 if (!ISDIGIT (*arg))
921 *character = *arg++;
922 if (*arg)
924 long int tmp_long;
925 if (xstrtol (arg, NULL, 10, &tmp_long, "") != LONGINT_OK
926 || tmp_long <= 0 || tmp_long > INT_MAX)
928 error (0, 0,
929 _("`-%c' extra characters or invalid number in the argument: `%s'"),
930 switch_char, arg);
931 usage (2);
933 *number = (int) tmp_long;
937 /* Set parameters related to formatting. */
939 static void
940 init_parameters (int number_of_files)
942 int chars_used_by_number = 0;
944 if (use_form_feed)
946 lines_per_header = 3;
947 lines_per_footer = 0;
950 lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
951 if (lines_per_body <= 0)
953 extremities = FALSE;
954 keep_FF = TRUE;
956 if (extremities == FALSE)
957 lines_per_body = lines_per_page;
959 if (double_space)
960 lines_per_body = lines_per_body / 2;
962 /* If input is stdin, cannot print parallel files. BSD dumps core
963 on this. */
964 if (number_of_files == 0)
965 parallel_files = FALSE;
967 if (parallel_files)
968 columns = number_of_files;
970 /* One file, multi columns down: -b option is set to get a consistent
971 formulation with "FF set by hand" in input files. */
972 if (storing_columns)
973 balance_columns = TRUE;
975 /* Tabification is assumed for multiple columns. */
976 if (columns > 1)
978 if (!use_col_separator)
980 /* Use default separator */
981 if (join_lines)
982 col_sep_string = line_separator;
983 else
984 col_sep_string = column_separator;
985 col_sep_length = 1;
986 use_col_separator = TRUE;
989 truncate_lines = TRUE;
990 untabify_input = TRUE;
991 tabify_output = TRUE;
993 else
994 storing_columns = FALSE;
996 /* -j dominates -w in any case */
997 if (join_lines)
998 truncate_lines = FALSE;
1000 if (numbered_lines)
1002 line_count = start_line_num;
1003 if (number_separator == input_tab_char)
1005 number_width = chars_per_number +
1006 TAB_WIDTH (chars_per_input_tab,
1007 (chars_per_margin + chars_per_number));
1009 else
1010 number_width = chars_per_number + 1;
1011 /* The number is part of the column width unless we are
1012 printing files in parallel. */
1013 if (parallel_files)
1014 chars_used_by_number = number_width;
1017 chars_per_column = (chars_per_line - chars_used_by_number -
1018 (columns - 1) * col_sep_length) / columns;
1020 if (chars_per_column < 1)
1021 error (EXIT_FAILURE, 0, _("page width too narrow"));
1023 if (numbered_lines)
1025 if (number_buff != NULL)
1026 free (number_buff);
1027 number_buff = (char *) xmalloc (2 * chars_per_number);
1030 /* Pick the maximum between the tab width and the width of an
1031 escape sequence. */
1032 if (clump_buff != NULL)
1033 free (clump_buff);
1034 clump_buff = (int *) xmalloc ((chars_per_input_tab > 4
1035 ? chars_per_input_tab : 4) * sizeof (int));
1038 /* Open the necessary files,
1039 maintaining a COLUMN structure for each column.
1041 With multiple files, each column p has a different p->fp.
1042 With single files, each column p has the same p->fp.
1043 Return 1 if (number_of_files > 0) and no files can be opened,
1044 0 otherwise.
1046 With each column/file p, p->full_page_printed is initialized,
1047 see also open_file. */
1049 static int
1050 init_fps (int number_of_files, char **av)
1052 int i, files_left;
1053 COLUMN *p;
1054 FILE *firstfp;
1055 char *firstname;
1057 total_files = 0;
1059 if (column_vector != NULLCOL)
1060 free ((char *) column_vector);
1061 column_vector = (COLUMN *) xmalloc (columns * sizeof (COLUMN));
1063 if (parallel_files)
1065 files_left = number_of_files;
1066 for (p = column_vector; files_left--; ++p, ++av)
1068 if (open_file (*av, p) == 0)
1070 --p;
1071 --columns;
1074 if (columns == 0)
1075 return 1;
1076 init_header ("", -1);
1078 else
1080 p = column_vector;
1081 if (number_of_files > 0)
1083 if (open_file (*av, p) == 0)
1084 return 1;
1085 init_header (*av, fileno (p->fp));
1086 p->lines_stored = 0;
1088 else
1090 p->name = _("standard input");
1091 p->fp = stdin;
1092 have_read_stdin = TRUE;
1093 p->status = OPEN;
1094 p->full_page_printed = FALSE;
1095 ++total_files;
1096 init_header ("", -1);
1097 p->lines_stored = 0;
1100 firstname = p->name;
1101 firstfp = p->fp;
1102 for (i = columns - 1, ++p; i; --i, ++p)
1104 p->name = firstname;
1105 p->fp = firstfp;
1106 p->status = OPEN;
1107 p->full_page_printed = FALSE;
1108 p->lines_stored = 0;
1111 files_ready_to_read = total_files;
1112 return 0;
1115 /* Determine print_func and char_func, the functions
1116 used by each column for printing and/or storing.
1118 Determine the horizontal position desired when we begin
1119 printing a column (p->start_position). */
1121 static void
1122 init_funcs (void)
1124 int i, h, h_next;
1125 COLUMN *p;
1127 h = chars_per_margin;
1129 if (!truncate_lines)
1130 h_next = ANYWHERE;
1131 else
1133 /* When numbering lines of parallel files, we enlarge the
1134 first column to accomodate the number. Looks better than
1135 the Sys V approach. */
1136 if (parallel_files && numbered_lines)
1137 h_next = h + chars_per_column + number_width;
1138 else
1139 h_next = h + chars_per_column;
1142 /* Enlarge p->start_position of first column to use the same form of
1143 padding_not_printed with all columns. */
1144 h = h + col_sep_length;
1146 /* This loop takes care of all but the rightmost column. */
1148 for (p = column_vector, i = 1; i < columns; ++p, ++i)
1150 if (storing_columns) /* One file, multi columns down. */
1152 p->char_func = store_char;
1153 p->print_func = print_stored;
1155 else
1156 /* One file, multi columns across; or parallel files. */
1158 p->char_func = print_char;
1159 p->print_func = read_line;
1162 /* Number only the first column when printing files in
1163 parallel. */
1164 p->numbered = numbered_lines && (!parallel_files || i == 1);
1165 p->start_position = h;
1167 /* If we don't truncate lines, all start_positions are
1168 ANYWHERE, except the first column's start_position when
1169 using a margin. */
1171 if (!truncate_lines)
1173 h = ANYWHERE;
1174 h_next = ANYWHERE;
1176 else
1178 h = h_next + col_sep_length;
1179 h_next = h + chars_per_column;
1183 /* The rightmost column.
1185 Doesn't need to be stored unless we intend to balance
1186 columns on the last page. */
1187 if (storing_columns && balance_columns)
1189 p->char_func = store_char;
1190 p->print_func = print_stored;
1192 else
1194 p->char_func = print_char;
1195 p->print_func = read_line;
1198 p->numbered = numbered_lines && (!parallel_files || i == 1);
1199 p->start_position = h;
1202 /* Open a file. Return nonzero if successful, zero if failed.
1204 With each file p, p->full_page_printed is initialized,
1205 see also init_fps. */
1207 static int
1208 open_file (char *name, COLUMN *p)
1210 if (!strcmp (name, "-"))
1212 p->name = _("standard input");
1213 p->fp = stdin;
1214 have_read_stdin = 1;
1216 else
1218 p->name = name;
1219 p->fp = fopen (name, "r");
1221 if (p->fp == NULL)
1223 ++failed_opens;
1224 if (!ignore_failed_opens)
1225 error (0, errno, "%s", name);
1226 return 0;
1228 p->status = OPEN;
1229 p->full_page_printed = FALSE;
1230 ++total_files;
1231 return 1;
1234 /* Close the file in P.
1236 If we aren't dealing with multiple files in parallel, we change
1237 the status of all columns in the column list to reflect the close. */
1239 static void
1240 close_file (COLUMN *p)
1242 COLUMN *q;
1243 int i;
1245 if (p->status == CLOSED)
1246 return;
1247 if (ferror (p->fp))
1248 error (EXIT_FAILURE, errno, "%s", p->name);
1249 if (p->fp != stdin && fclose (p->fp) == EOF)
1250 error (EXIT_FAILURE, errno, "%s", p->name);
1252 if (!parallel_files)
1254 for (q = column_vector, i = columns; i; ++q, --i)
1256 q->status = CLOSED;
1257 if (q->lines_stored == 0)
1259 q->lines_to_print = 0;
1263 else
1265 p->status = CLOSED;
1266 p->lines_to_print = 0;
1269 --files_ready_to_read;
1272 /* Put a file on hold until we start a new page,
1273 since we've hit a form feed.
1275 If we aren't dealing with parallel files, we must change the
1276 status of all columns in the column list. */
1278 static void
1279 hold_file (COLUMN *p)
1281 COLUMN *q;
1282 int i;
1284 if (!parallel_files)
1285 for (q = column_vector, i = columns; i; ++q, --i)
1287 if (storing_columns)
1288 q->status = FF_FOUND;
1289 else
1290 q->status = ON_HOLD;
1292 else
1293 p->status = ON_HOLD;
1295 p->lines_to_print = 0;
1296 --files_ready_to_read;
1299 /* Undo hold_file -- go through the column list and change any
1300 ON_HOLD columns to OPEN. Used at the end of each page. */
1302 static void
1303 reset_status (void)
1305 int i = columns;
1306 COLUMN *p;
1308 for (p = column_vector; i; --i, ++p)
1309 if (p->status == ON_HOLD)
1311 p->status = OPEN;
1312 files_ready_to_read++;
1315 if (storing_columns)
1316 files_ready_to_read = 1;
1319 /* Print a single file, or multiple files in parallel.
1321 Set up the list of columns, opening the necessary files.
1322 Allocate space for storing columns, if necessary.
1323 Skip to first_page_number, if user has asked to skip leading pages.
1324 Determine which functions are appropriate to store/print lines
1325 in each column.
1326 Print the file(s). */
1328 static void
1329 print_files (int number_of_files, char **av)
1331 init_parameters (number_of_files);
1332 if (init_fps (number_of_files, av))
1333 return;
1334 if (storing_columns)
1335 init_store_cols ();
1337 if (first_page_number > 1)
1339 if (!skip_to_page (first_page_number))
1340 return;
1341 else
1342 page_number = first_page_number;
1344 else
1345 page_number = 1;
1347 init_funcs ();
1349 line_number = line_count;
1350 while (print_page ())
1354 /* Estimate the number of characters taken up by a short format date and
1355 time: "yy-mm-dd HH:MM" and: "Page NNNN". */
1356 #define CHARS_FOR_DATE_AND_PAGE 23
1358 /* Initialize header information.
1359 If DESC is non-negative, it is a file descriptor open to
1360 FILENAME for reading.
1362 Allocate space for a header string,
1363 Determine the time, insert file name or user-specified string.
1364 Make use of a centered header with left-hand-side truncation marked by
1365 a '*` in front, if necessary. */
1367 static void
1368 init_header (char *filename, int desc)
1370 int chars_per_middle, chars_free, lhs_blanks, rhs_blanks;
1371 char *f = filename;
1372 char *no_middle = "";
1373 char *header_text;
1374 struct tm *tmptr;
1375 struct stat st;
1376 char *datim = "- Date/Time --";
1378 if (filename == NULL)
1379 f = "";
1381 if (header != NULL)
1382 free (header);
1383 header = (char *) xmalloc (chars_per_line + 1);
1385 if (!standard_header && *custom_header == '\0')
1386 sprintf (header, "%s", " "); /* blank line header */
1387 else
1389 #define T_BUF_FMT "%Y-%m-%d %H:%M" /* date/time short format */
1390 #define T_BUF_SIZE 17 /* FIXME: using a literal here is fragile. */
1391 char t_buf[T_BUF_SIZE];
1393 /* If parallel files or standard input, use current time. */
1394 if (desc < 0 || !strcmp (filename, "-") || fstat (desc, &st))
1395 st.st_mtime = time (NULL);
1397 tmptr = localtime (&st.st_mtime);
1398 strftime (t_buf, T_BUF_SIZE, T_BUF_FMT, tmptr);
1400 chars_per_middle = chars_per_line - CHARS_FOR_DATE_AND_PAGE;
1401 if (chars_per_middle < 3)
1403 header_text = no_middle; /* Nothing free for a heading */
1404 lhs_blanks = 1;
1405 rhs_blanks = 1;
1407 else
1409 header_text = standard_header ? f : custom_header;
1410 chars_free = chars_per_middle - (int) strlen (header_text);
1411 if (chars_free > 1)
1413 lhs_blanks = chars_free / 2; /* text not truncated */
1414 rhs_blanks = chars_free - lhs_blanks;
1416 else
1417 { /* lhs truncation */
1418 header_text = header_text - chars_free + 2;
1419 *header_text = '*';
1420 lhs_blanks = 1;
1421 rhs_blanks = 1;
1425 sprintf (header, _("%s%*s%s%*sPage"), (test_suite ? datim : t_buf),
1426 lhs_blanks, " ", header_text, rhs_blanks, " ");
1430 /* Set things up for printing a page
1432 Scan through the columns ...
1433 Determine which are ready to print
1434 (i.e., which have lines stored or open files)
1435 Set p->lines_to_print appropriately
1436 (to p->lines_stored if we're storing, or lines_per_body
1437 if we're reading straight from the file)
1438 Keep track of this total so we know when to stop printing */
1440 static void
1441 init_page (void)
1443 int j;
1444 COLUMN *p;
1446 if (storing_columns)
1448 store_columns ();
1449 for (j = columns - 1, p = column_vector; j; --j, ++p)
1451 p->lines_to_print = p->lines_stored;
1454 /* Last column. */
1455 if (balance_columns)
1457 p->lines_to_print = p->lines_stored;
1459 /* Since we're not balancing columns, we don't need to store
1460 the rightmost column. Read it straight from the file. */
1461 else
1463 if (p->status == OPEN)
1465 p->lines_to_print = lines_per_body;
1467 else
1468 p->lines_to_print = 0;
1471 else
1472 for (j = columns, p = column_vector; j; --j, ++p)
1473 if (p->status == OPEN)
1475 p->lines_to_print = lines_per_body;
1477 else
1478 p->lines_to_print = 0;
1481 /* Align empty columns and print separators.
1482 Empty columns will be formed by files with status ON_HOLD or CLOSED
1483 when printing multiple files in parallel. */
1485 static void
1486 align_column (COLUMN *p)
1488 padding_not_printed = p->start_position;
1489 if (padding_not_printed - col_sep_length > 0)
1491 pad_across_to (padding_not_printed - col_sep_length);
1492 padding_not_printed = ANYWHERE;
1495 if (use_col_separator)
1496 print_sep_string ();
1498 if (p->numbered)
1499 add_line_number (p);
1502 /* Print one page.
1504 As long as there are lines left on the page and columns ready to print,
1505 Scan across the column list
1506 if the column has stored lines or the file is open
1507 pad to the appropriate spot
1508 print the column
1509 pad the remainder of the page with \n or \f as requested
1510 reset the status of all files -- any files which where on hold because
1511 of formfeeds are now put back into the lineup. */
1513 static int
1514 print_page (void)
1516 int j;
1517 int lines_left_on_page;
1518 COLUMN *p;
1520 /* Used as an accumulator (with | operator) of successive values of
1521 pad_vertically. The trick is to set pad_vertically
1522 to zero before each run through the inner loop, then after that
1523 loop, it tells us whether a line was actually printed (whether a
1524 newline needs to be output -- or two for double spacing). But those
1525 values have to be accumulated (in pv) so we can invoke pad_down
1526 properly after the outer loop completes. */
1527 int pv;
1529 init_page ();
1531 if (cols_ready_to_print () == 0)
1532 return FALSE;
1534 if (extremities)
1535 print_a_header = TRUE;
1537 /* Don't pad unless we know a page was printed. */
1538 pad_vertically = FALSE;
1539 pv = FALSE;
1541 lines_left_on_page = lines_per_body;
1542 if (double_space)
1543 lines_left_on_page *= 2;
1545 while (lines_left_on_page > 0 && cols_ready_to_print () > 0)
1547 output_position = 0;
1548 spaces_not_printed = 0;
1549 separators_not_printed = 0;
1550 pad_vertically = FALSE;
1551 align_empty_cols = FALSE;
1552 empty_line = TRUE;
1554 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1556 input_position = 0;
1557 if (p->lines_to_print > 0 || p->status == FF_FOUND)
1559 FF_only = FALSE;
1560 padding_not_printed = p->start_position;
1561 if (!(p->print_func) (p))
1562 read_rest_of_line (p);
1563 pv |= pad_vertically;
1565 --p->lines_to_print;
1566 if (p->lines_to_print <= 0)
1568 if (cols_ready_to_print () <= 0)
1569 break;
1572 /* File p changed its status to ON_HOLD or CLOSED */
1573 if (parallel_files && p->status != OPEN)
1575 if (empty_line)
1576 align_empty_cols = TRUE;
1577 else if (p->status == CLOSED ||
1578 (p->status == ON_HOLD && FF_only))
1579 align_column (p);
1582 else if (parallel_files)
1584 /* File status ON_HOLD or CLOSED */
1585 if (empty_line)
1586 align_empty_cols = TRUE;
1587 else
1588 align_column (p);
1591 /* We need it also with an empty column */
1592 if (use_col_separator)
1593 ++separators_not_printed;
1596 if (pad_vertically)
1598 putchar ('\n');
1599 --lines_left_on_page;
1602 if (double_space && pv && extremities)
1604 putchar ('\n');
1605 --lines_left_on_page;
1609 if (lines_left_on_page == 0)
1610 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1611 if (p->status == OPEN)
1612 p->full_page_printed = TRUE;
1614 pad_vertically = pv;
1616 if (pad_vertically && extremities)
1617 pad_down (lines_left_on_page + lines_per_footer);
1618 else if (keep_FF && print_a_FF)
1620 putchar ('\f');
1621 print_a_FF = FALSE;
1624 if (last_page_number && page_number > last_page_number)
1625 return FALSE; /* Stop printing with LAST_PAGE */
1627 reset_status (); /* Change ON_HOLD to OPEN. */
1629 return TRUE; /* More pages to go. */
1632 /* Allocate space for storing columns.
1634 This is necessary when printing multiple columns from a single file.
1635 Lines are stored consecutively in buff, separated by '\0'.
1637 The following doesn't apply any longer - any tuning possible?
1638 (We can't use a fixed offset since with the '-s' flag lines aren't
1639 truncated.)
1641 We maintain a list (line_vector) of pointers to the beginnings
1642 of lines in buff. We allocate one more than the number of lines
1643 because the last entry tells us the index of the last character,
1644 which we need to know in order to print the last line in buff. */
1646 static void
1647 init_store_cols (void)
1649 int total_lines = lines_per_body * columns;
1650 int chars_if_truncate = total_lines * (chars_per_column + 1);
1652 if (line_vector != NULL)
1653 free ((int *) line_vector);
1654 /* FIXME: here's where it was allocated. */
1655 line_vector = (int *) xmalloc ((total_lines + 1) * sizeof (int *));
1657 if (end_vector != NULL)
1658 free ((int *) end_vector);
1659 end_vector = (int *) xmalloc (total_lines * sizeof (int *));
1661 if (buff != NULL)
1662 free (buff);
1663 buff_allocated = (use_col_separator
1664 ? 2 * chars_if_truncate
1665 : chars_if_truncate); /* Tune this. */
1666 buff = (char *) xmalloc (buff_allocated);
1669 /* Store all but the rightmost column.
1670 (Used when printing a single file in multiple downward columns)
1672 For each column
1673 set p->current_line to be the index in line_vector of the
1674 first line in the column
1675 For each line in the column
1676 store the line in buff
1677 add to line_vector the index of the line's first char
1678 buff_start is the index in buff of the first character in the
1679 current line. */
1681 static void
1682 store_columns (void)
1684 int i, j;
1685 int line = 0;
1686 int buff_start;
1687 int last_col; /* The rightmost column which will be saved in buff */
1688 COLUMN *p;
1690 buff_current = 0;
1691 buff_start = 0;
1693 if (balance_columns)
1694 last_col = columns;
1695 else
1696 last_col = columns - 1;
1698 for (i = 1, p = column_vector; i <= last_col; ++i, ++p)
1699 p->lines_stored = 0;
1701 for (i = 1, p = column_vector; i <= last_col && files_ready_to_read;
1702 ++i, ++p)
1704 p->current_line = line;
1705 for (j = lines_per_body; j && files_ready_to_read; --j)
1707 if (p->status == OPEN) /* Redundant. Clean up. */
1709 input_position = 0;
1711 if (!read_line (p))
1712 read_rest_of_line (p);
1714 if (p->status == OPEN
1715 || buff_start != buff_current)
1717 ++p->lines_stored;
1718 line_vector[line] = buff_start;
1719 end_vector[line++] = input_position;
1720 buff_start = buff_current;
1725 /* Keep track of the location of the last char in buff. */
1726 line_vector[line] = buff_start;
1728 if (balance_columns && p->lines_stored != lines_per_body)
1729 balance (line);
1732 static void
1733 balance (int total_stored)
1735 COLUMN *p;
1736 int i, lines;
1737 int first_line = 0;
1739 for (i = 1, p = column_vector; i <= columns; ++i, ++p)
1741 lines = total_stored / columns;
1742 if (i <= total_stored % columns)
1743 ++lines;
1745 p->lines_stored = lines;
1746 p->current_line = first_line;
1748 first_line += lines;
1752 /* Store a character in the buffer. */
1754 static void
1755 store_char (int c)
1757 if (buff_current >= buff_allocated)
1759 /* May be too generous. */
1760 buff_allocated = 2 * buff_allocated;
1761 buff = (char *) xrealloc (buff, buff_allocated * sizeof (char));
1763 buff[buff_current++] = (char) c;
1766 static void
1767 add_line_number (COLUMN *p)
1769 int i;
1770 char *s;
1772 sprintf (number_buff, "%*d", chars_per_number, line_number++);
1773 s = number_buff;
1774 for (i = chars_per_number; i > 0; i--)
1775 (p->char_func) ((int) *s++);
1777 if (number_separator == input_tab_char)
1779 i = number_width - chars_per_number;
1780 while (i-- > 0)
1781 (p->char_func) ((int) ' ');
1783 else
1784 (p->char_func) ((int) number_separator);
1786 if (truncate_lines && !parallel_files)
1787 input_position += number_width;
1790 /* Print (or store) padding until the current horizontal position
1791 is position. */
1793 static void
1794 pad_across_to (int position)
1796 register int h = output_position;
1798 if (tabify_output)
1799 spaces_not_printed = position - output_position;
1800 else
1802 while (++h <= position)
1803 putchar (' ');
1804 output_position = position;
1808 /* Pad to the bottom of the page.
1810 If the user has requested a formfeed, use one.
1811 Otherwise, use newlines. */
1813 static void
1814 pad_down (int lines)
1816 register int i;
1818 if (use_form_feed)
1819 putchar ('\f');
1820 else
1821 for (i = lines; i; --i)
1822 putchar ('\n');
1825 /* Read the rest of the line.
1827 Read from the current column's file until an end of line is
1828 hit. Used when we've truncated a line and we no longer need
1829 to print or store its characters. */
1831 static void
1832 read_rest_of_line (COLUMN *p)
1834 register int c;
1835 FILE *f = p->fp;
1837 while ((c = getc (f)) != '\n')
1839 if (c == '\f')
1841 if ((c = getc (f)) != '\n')
1842 ungetc (c, f);
1843 if (keep_FF)
1844 print_a_FF = TRUE;
1845 hold_file (p);
1846 break;
1848 else if (c == EOF)
1850 close_file (p);
1851 break;
1856 /* Read a line with skip_to_page.
1858 Read from the current column's file until an end of line is
1859 hit. Used when we read full lines to skip pages.
1860 With skip_to_page we have to check for FF-coincidence which is done
1861 in function read_line otherwise.
1862 Count lines of skipped pages to find the line number of 1st page
1863 printed relative to 1st line of input file (start_line_num). */
1865 static void
1866 skip_read (COLUMN *p, int column_number)
1868 register int c;
1869 FILE *f = p->fp;
1870 int i, single_ff = FALSE;
1871 COLUMN *q;
1873 /* Read 1st character in a line or any character succeeding a FF */
1874 if ((c = getc (f)) == '\f' && p->full_page_printed)
1875 /* A FF-coincidence with a previous full_page_printed.
1876 To avoid an additional empty page, eliminate the FF */
1877 if ((c = getc (f)) == '\n')
1878 c = getc (f);
1880 p->full_page_printed = FALSE;
1882 /* 1st character a FF means a single FF without any printable
1883 characters. Don't count it as a line with -n option. */
1884 if (c == '\f')
1885 single_ff = TRUE;
1887 /* Preparing for a FF-coincidence: Maybe we finish that page
1888 without a FF found */
1889 if (last_line)
1890 p->full_page_printed = TRUE;
1892 while (c != '\n')
1894 if (c == '\f')
1896 /* No FF-coincidence possible,
1897 no catching up of a FF-coincidence with next page */
1898 if (last_line)
1900 if (!parallel_files)
1901 for (q = column_vector, i = columns; i; ++q, --i)
1902 q->full_page_printed = FALSE;
1903 else
1904 p->full_page_printed = FALSE;
1907 if ((c = getc (f)) != '\n')
1908 ungetc (c, f);
1909 hold_file (p);
1910 break;
1912 else if (c == EOF)
1914 close_file (p);
1915 break;
1917 c = getc (f);
1920 if (skip_count)
1921 if ((!parallel_files || column_number == 1) && !single_ff)
1922 ++line_count;
1925 /* If we're tabifying output,
1927 When print_char encounters white space it keeps track
1928 of our desired horizontal position and delays printing
1929 until this function is called. */
1931 static void
1932 print_white_space (void)
1934 register int h_new;
1935 register int h_old = output_position;
1936 register int goal = h_old + spaces_not_printed;
1938 while (goal - h_old > 1
1939 && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal)
1941 putchar (output_tab_char);
1942 h_old = h_new;
1944 while (++h_old <= goal)
1945 putchar (' ');
1947 output_position = goal;
1948 spaces_not_printed = 0;
1951 /* Print column separators.
1953 We keep a count until we know that we'll be printing a line,
1954 then print_sep_string() is called. */
1956 static void
1957 print_sep_string ()
1959 char *s;
1960 int l = col_sep_length;
1962 s = col_sep_string;
1964 if (spaces_not_printed > 0)
1965 print_white_space ();
1967 for (; separators_not_printed > 0; --separators_not_printed)
1969 while (l-- > 0)
1970 putchar (*s++);
1971 output_position += col_sep_length;
1975 /* Print (or store, depending on p->char_func) a clump of N
1976 characters. */
1978 static void
1979 print_clump (COLUMN *p, int n, int *clump)
1981 while (n--)
1982 (p->char_func) (*clump++);
1985 /* Print a character.
1987 Update the following comment: process-char hasn't been used any
1988 longer.
1989 If we're tabifying, all tabs have been converted to spaces by
1990 process_char(). Keep a count of consecutive spaces, and when
1991 a nonspace is encountered, call print_white_space() to print the
1992 required number of tabs and spaces. */
1994 static void
1995 print_char (int c)
1997 if (tabify_output)
1999 if (c == ' ')
2001 ++spaces_not_printed;
2002 return;
2004 else if (spaces_not_printed > 0)
2005 print_white_space ();
2007 /* Nonprintables are assumed to have width 0, except '\b'. */
2008 if (!ISPRINT (c))
2010 if (c == '\b')
2011 --output_position;
2013 else
2014 ++output_position;
2016 putchar (c);
2019 /* Skip to page PAGE before printing. */
2021 static int
2022 skip_to_page (int page)
2024 int n, i, j;
2025 COLUMN *p;
2027 for (n = 1; n < page; ++n)
2029 for (i = 1; i < lines_per_body; ++i)
2031 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2032 if (p->status == OPEN)
2033 skip_read (p, j);
2035 last_line = TRUE;
2036 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2037 if (p->status == OPEN)
2038 skip_read (p, j);
2040 if (storing_columns) /* change FF_FOUND to ON_HOLD */
2041 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2042 p->status = ON_HOLD;
2044 reset_status ();
2045 last_line = FALSE;
2047 return files_ready_to_read > 0;
2050 /* Print a header.
2052 Formfeeds are assumed to use up two lines at the beginning of
2053 the page. */
2055 static void
2056 print_header (void)
2058 if (!use_form_feed)
2059 fprintf (stdout, "\n\n");
2061 output_position = 0;
2062 pad_across_to (chars_per_margin);
2063 print_white_space ();
2065 if (!standard_header && *custom_header == '\0')
2066 fprintf (stdout, "%s\n\n\n", header);
2067 else
2068 fprintf (stdout, "%s%5d\n\n\n", header, page_number++);
2070 print_a_header = FALSE;
2071 output_position = 0;
2074 /* Print (or store, if p->char_func is store_char()) a line.
2076 Read a character to determine whether we have a line or not.
2077 (We may hit EOF, \n, or \f)
2079 Once we know we have a line,
2080 set pad_vertically = TRUE, meaning it's safe
2081 to pad down at the end of the page, since we do have a page.
2082 print a header if needed.
2083 pad across to padding_not_printed if needed.
2084 print any separators which need to be printed.
2085 print a line number if it needs to be printed.
2087 Print the clump which corresponds to the first character.
2089 Enter a loop and keep printing until an end of line condition
2090 exists, or until we exceed chars_per_column.
2092 Return FALSE if we exceed chars_per_column before reading
2093 an end of line character, TRUE otherwise. */
2095 static int
2096 read_line (COLUMN *p)
2098 register int c, chars;
2099 int last_input_position;
2100 int j, k;
2101 COLUMN *q;
2103 /* Suppress `used before initialized' warning. */
2104 #ifdef lint
2105 chars = 0;
2106 #endif
2108 /* read 1st character in each line or any character succeeding a FF: */
2109 c = getc (p->fp);
2111 last_input_position = input_position;
2113 if (c == '\f' && p->full_page_printed)
2114 if ((c = getc (p->fp)) == '\n')
2115 c = getc (p->fp);
2116 p->full_page_printed = FALSE;
2118 switch (c)
2120 case '\f':
2121 if ((c = getc (p->fp)) != '\n')
2122 ungetc (c, p->fp);
2123 FF_only = TRUE;
2124 if (print_a_header && !storing_columns)
2126 pad_vertically = TRUE;
2127 print_header ();
2129 else if (keep_FF)
2130 print_a_FF = TRUE;
2131 hold_file (p);
2132 return TRUE;
2133 case EOF:
2134 close_file (p);
2135 return TRUE;
2136 case '\n':
2137 break;
2138 default:
2139 chars = char_to_clump (c);
2142 if (truncate_lines && input_position > chars_per_column)
2144 input_position = last_input_position;
2145 return FALSE;
2148 if (p->char_func != store_char)
2150 pad_vertically = TRUE;
2152 if (print_a_header && !storing_columns)
2153 print_header ();
2155 if (parallel_files && align_empty_cols)
2157 /* We have to align empty columns at the beginning of a line. */
2158 k = separators_not_printed;
2159 separators_not_printed = 0;
2160 for (j = 1, q = column_vector; j <= k; ++j, ++q)
2162 align_column (q);
2163 separators_not_printed += 1;
2165 padding_not_printed = p->start_position;
2166 if (truncate_lines)
2167 spaces_not_printed = chars_per_column;
2168 else
2169 spaces_not_printed = 0;
2170 align_empty_cols = FALSE;
2173 if (padding_not_printed - col_sep_length > 0)
2175 pad_across_to (padding_not_printed - col_sep_length);
2176 padding_not_printed = ANYWHERE;
2179 if (use_col_separator)
2180 print_sep_string ();
2183 if (p->numbered)
2184 add_line_number (p);
2186 empty_line = FALSE;
2187 if (c == '\n')
2188 return TRUE;
2190 print_clump (p, chars, clump_buff);
2192 for (;;)
2194 c = getc (p->fp);
2196 switch (c)
2198 case '\n':
2199 return TRUE;
2200 case '\f':
2201 if ((c = getc (p->fp)) != '\n')
2202 ungetc (c, p->fp);
2203 if (keep_FF)
2204 print_a_FF = TRUE;
2205 hold_file (p);
2206 return TRUE;
2207 case EOF:
2208 close_file (p);
2209 return TRUE;
2212 last_input_position = input_position;
2213 chars = char_to_clump (c);
2214 if (truncate_lines && input_position > chars_per_column)
2216 input_position = last_input_position;
2217 return FALSE;
2220 print_clump (p, chars, clump_buff);
2224 /* Print a line from buff.
2226 If this function has been called, we know we have "something to
2227 print". But it remains to be seen whether we have a real text page
2228 or an empty page (a single form feed) with/without a header only.
2229 Therefore first we set pad_vertically to TRUE and print a header
2230 if necessary.
2231 If FF_FOUND and we are using -t|-T option we omit any newline by
2232 setting pad_vertically to FALSE (see print_page).
2233 Otherwise we pad across if necessary, print separators if necessary
2234 and text of COLUMN *p.
2236 Return TRUE, meaning there is no need to call read_rest_of_line. */
2238 static int
2239 print_stored (COLUMN *p)
2241 COLUMN *q;
2242 int i;
2244 int line = p->current_line++;
2245 register char *first = &buff[line_vector[line]];
2246 /* FIXME
2247 UMR: Uninitialized memory read:
2248 * This is occurring while in:
2249 print_stored [pr.c:2239]
2250 * Reading 4 bytes from 0x5148c in the heap.
2251 * Address 0x5148c is 4 bytes into a malloc'd block at 0x51488 of 676 bytes
2252 * This block was allocated from:
2253 malloc [rtlib.o]
2254 xmalloc [xmalloc.c:94]
2255 init_store_cols [pr.c:1648]
2257 register char *last = &buff[line_vector[line + 1]];
2259 pad_vertically = TRUE;
2261 if (print_a_header)
2262 print_header ();
2264 if (p->status == FF_FOUND)
2266 for (i = 1, q = column_vector; i <= columns; ++i, ++q)
2267 q->status = ON_HOLD;
2268 if (column_vector->lines_to_print <= 0)
2270 if (!extremities)
2271 pad_vertically = FALSE;
2272 return TRUE; /* print a header only */
2276 if (padding_not_printed - col_sep_length > 0)
2278 pad_across_to (padding_not_printed - col_sep_length);
2279 padding_not_printed = ANYWHERE;
2282 if (use_col_separator)
2283 print_sep_string ();
2285 while (first != last)
2286 print_char (*first++);
2288 if (spaces_not_printed == 0)
2290 output_position = p->start_position + end_vector[line];
2291 if (p->start_position - col_sep_length == chars_per_margin)
2292 output_position -= col_sep_length;
2295 return TRUE;
2298 /* Convert a character to the proper format and return the number of
2299 characters in the resulting clump. Increment input_position by
2300 the width of the clump.
2302 Tabs are converted to clumps of spaces.
2303 Nonprintable characters may be converted to clumps of escape
2304 sequences or control prefixes.
2306 Note: the width of a clump is not necessarily equal to the number of
2307 characters in clump_buff. (e.g, the width of '\b' is -1, while the
2308 number of characters is 1.) */
2310 static int
2311 char_to_clump (int c)
2313 register int *s = clump_buff;
2314 register int i;
2315 char esc_buff[4];
2316 int width;
2317 int chars;
2319 if (c == input_tab_char)
2321 width = TAB_WIDTH (chars_per_input_tab, input_position);
2323 if (untabify_input)
2325 for (i = width; i; --i)
2326 *s++ = ' ';
2327 chars = width;
2329 else
2331 *s = c;
2332 chars = 1;
2336 else if (!ISPRINT (c))
2338 if (use_esc_sequence)
2340 width = 4;
2341 chars = 4;
2342 *s++ = '\\';
2343 sprintf (esc_buff, "%03o", c);
2344 for (i = 0; i <= 2; ++i)
2345 *s++ = (int) esc_buff[i];
2347 else if (use_cntrl_prefix)
2349 if (c < 0200)
2351 width = 2;
2352 chars = 2;
2353 *s++ = '^';
2354 *s++ = c ^ 0100;
2356 else
2358 width = 4;
2359 chars = 4;
2360 *s++ = '\\';
2361 sprintf (esc_buff, "%03o", c);
2362 for (i = 0; i <= 2; ++i)
2363 *s++ = (int) esc_buff[i];
2366 else if (c == '\b')
2368 width = -1;
2369 chars = 1;
2370 *s = c;
2372 else
2374 width = 0;
2375 chars = 1;
2376 *s = c;
2379 else
2381 width = 1;
2382 chars = 1;
2383 *s = c;
2386 input_position += width;
2387 return chars;
2390 /* We've just printed some files and need to clean up things before
2391 looking for more options and printing the next batch of files.
2393 Free everything we've xmalloc'ed, except `header'. */
2395 static void
2396 cleanup (void)
2398 if (number_buff)
2399 free (number_buff);
2400 if (clump_buff)
2401 free (clump_buff);
2402 if (column_vector)
2403 free (column_vector);
2404 if (line_vector)
2405 free (line_vector);
2406 if (end_vector)
2407 free (end_vector);
2408 if (buff)
2409 free (buff);
2412 /* Complain, print a usage message, and die. */
2414 static void
2415 usage (int status)
2417 if (status != 0)
2418 fprintf (stderr, _("Try `%s --help' for more information.\n"),
2419 program_name);
2420 else
2422 printf (_("\
2423 Usage: %s [OPTION]... [FILE]...\n\
2425 program_name);
2427 printf (_("\
2428 Paginate or columnate FILE(s) for printing.\n\
2430 +FIRST_PAGE[:LAST_PAGE]\n\
2431 begin [stop] printing with page FIRST_[LAST_]PAGE\n\
2432 -COLUMN produce COLUMN-column output and print columns down,\n\
2433 unless -a is used. Balance number of lines in the\n\
2434 columns on each page.\n\
2435 -a print columns across rather than down, used together\n\
2436 with -COLUMN\n\
2437 -c use hat notation (^G) and octal backslash notation\n\
2438 -d double space the output\n\
2439 -e[CHAR[WIDTH]] expand input CHARs (TABs) to tab WIDTH (8)\n\
2440 -F, -f use form feeds instead of newlines to separate pages\n\
2441 (by a 3-line page header with -f or a 5-line header\n\
2442 and trailer without -f)\n\
2443 -h HEADER use a centered HEADER instead of filename in page headers\n\
2444 with long headers left-hand-side truncation may occur\n\
2445 -h \"\" prints a blank line. Don't use -h\"\"\n\
2446 -i[CHAR[WIDTH]] replace spaces with CHARs (TABs) to tab WIDTH (8)\n\
2447 -j merge full lines, turns off -w line truncation, no column\n\
2448 alignment, -s[STRING] sets separators\n\
2449 -l PAGE_LENGTH set the page length to PAGE_LENGTH (66) lines\n\
2450 (default number of lines of text 56, with -f 63)\n"));
2451 printf (_("\
2452 -m print all files in parallel, one in each column,\n\
2453 truncate lines, but join lines of full length with -j\n\
2454 -n[SEP[DIGITS]] number lines, use DIGITS (5) digits, then SEP (TAB)\n\
2455 default counting starts with 1st line of input file\n\
2456 -N NUMBER start counting with NUMBER at 1st line of first\n\
2457 page printed (see +FIRST_PAGE)\n\
2458 -o MARGIN offset each line with MARGIN spaces (do not affect -w)\n\
2459 -r inhibit warning when a file cannot be opened\n\
2460 -s[STRING] separate columns by an optional STRING, don't use\n\
2461 -s \"STRING\", -s only: No separator used (same as -s\"\"),\n\
2462 without -s: Default separator \'TAB\' with -j and \'space\'\n\
2463 otherwise (same as -s\" \")\n\
2464 -t inhibit page headers and trailers\n\
2465 -T inhibit page headers and trailers, eliminate any page\n\
2466 layout by form feeds set in input files\n\
2467 -v use octal backslash notation\n\
2468 -w PAGE_WIDTH set page width to PAGE_WIDTH (72) columns, truncate\n\
2469 lines (see also -j option)\n\
2470 --help display this help and exit\n\
2471 --version output version information and exit\n\
2473 -T implied by -l nn when nn <= 10 or <= 3 with -f. With no FILE, or when\n\
2474 FILE is -, read standard input.\n\
2475 "));
2476 puts (_("\nReport bugs to <textutils-bugs@gnu.ai.mit.edu>."));
2478 exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);