[EXIT_FAILURE]: Define.
[coreutils.git] / src / pr.c
blob01ddef60830906f4f8bb114c08a9646446f7a96b
1 /* pr -- convert text files for printing.
2 Copyright (C) 88, 91, 95, 96, 1997, 1998 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 #ifndef TRUE
182 # define TRUE 1
183 # define FALSE 0
184 #endif
186 /* Used with start_position in the struct COLUMN described below.
187 If start_position == ANYWHERE, we aren't truncating columns and
188 can begin printing a column anywhere. Otherwise we must pad to
189 the horizontal position start_position. */
190 #define ANYWHERE 0
192 /* Each column has one of these structures allocated for it.
193 If we're only dealing with one file, fp is the same for all
194 columns.
196 The general strategy is to spend time setting up these column
197 structures (storing columns if necessary), after which printing
198 is a matter of flitting from column to column and calling
199 print_func.
201 Parallel files, single files printing across in multiple
202 columns, and single files printing down in multiple columns all
203 fit the same printing loop.
205 print_func Function used to print lines in this column.
206 If we're storing this column it will be
207 print_stored(), Otherwise it will be read_line().
209 char_func Function used to process characters in this column.
210 If we're storing this column it will be store_char(),
211 otherwise it will be print_char().
213 current_line Index of the current entry in line_vector, which
214 contains the index of the first character of the
215 current line in buff[].
217 lines_stored Number of lines in this column which are stored in
218 buff.
220 lines_to_print If we're storing this column, lines_to_print is
221 the number of stored_lines which remain to be
222 printed. Otherwise it is the number of lines
223 we can print without exceeding lines_per_body.
225 start_position The horizontal position we want to be in before we
226 print the first character in this column.
228 numbered True means precede this column with a line number. */
230 struct COLUMN
232 FILE *fp; /* Input stream for this column. */
233 char *name; /* File name. */
234 enum
236 OPEN,
237 FF_FOUND, /* used with -b option, set with \f, changed
238 to ON_HOLD after print_header */
239 ON_HOLD, /* Hit a form feed. */
240 CLOSED
242 status; /* Status of the file pointer. */
243 int (*print_func) (); /* Func to print lines in this col. */
244 void (*char_func) (); /* Func to print/store chars in this col. */
245 int current_line; /* Index of current place in line_vector. */
246 int lines_stored; /* Number of lines stored in buff. */
247 int lines_to_print; /* No. lines stored or space left on page. */
248 int start_position; /* Horizontal position of first char. */
249 int numbered;
250 int full_page_printed; /* True means printed without a FF found. */
252 /* p->full_page_printed controls a special case of "FF set by hand":
253 True means a full page has been printed without FF found. To avoid an
254 additional empty page we have to ignore a FF immediately following in
255 the next line. */
258 typedef struct COLUMN COLUMN;
260 #define NULLCOL (COLUMN *)0
262 static int char_to_clump PARAMS ((int c));
263 static int read_line PARAMS ((COLUMN *p));
264 static int print_page PARAMS ((void));
265 static int print_stored PARAMS ((COLUMN *p));
266 static int open_file PARAMS ((char *name, COLUMN *p));
267 static int skip_to_page PARAMS ((int page));
268 static void print_header PARAMS ((void));
269 static void pad_across_to PARAMS ((int position));
270 static void add_line_number PARAMS ((COLUMN *p));
271 static void getoptarg PARAMS ((char *arg, char switch_char, char *character,
272 int *number));
273 static void usage PARAMS ((int status));
274 static void print_files PARAMS ((int number_of_files, char **av));
275 static void init_parameters PARAMS ((int number_of_files));
276 static void init_header PARAMS ((char *filename, int desc));
277 static void init_store_cols PARAMS ((void));
278 static void store_columns PARAMS ((void));
279 static void balance PARAMS ((int total_stored));
280 static void store_char PARAMS ((int c));
281 static void pad_down PARAMS ((int lines));
282 static void read_rest_of_line PARAMS ((COLUMN *p));
283 static void skip_read PARAMS ((COLUMN *p, int column_number));
284 static void print_char PARAMS ((int c));
285 static void cleanup PARAMS ((void));
286 static void first_last_page PARAMS ((char *pages));
287 static void print_sep_string PARAMS ((void));
288 static void separator_string PARAMS ((const char *optarg_S));
290 /* The name under which this program was invoked. */
291 char *program_name;
293 /* All of the columns to print. */
294 static COLUMN *column_vector;
296 /* When printing a single file in multiple downward columns,
297 we store the leftmost columns contiguously in buff.
298 To print a line from buff, get the index of the first character
299 from line_vector[i], and print up to line_vector[i + 1]. */
300 static char *buff;
302 /* Index of the position in buff where the next character
303 will be stored. */
304 static int buff_current;
306 /* The number of characters in buff.
307 Used for allocation of buff and to detect overflow of buff. */
308 static int buff_allocated;
310 /* Array of indices into buff.
311 Each entry is an index of the first character of a line.
312 This is used when storing lines to facilitate shuffling when
313 we do column balancing on the last page. */
314 static int *line_vector;
316 /* Array of horizonal positions.
317 For each line in line_vector, end_vector[line] is the horizontal
318 position we are in after printing that line. We keep track of this
319 so that we know how much we need to pad to prepare for the next
320 column. */
321 static int *end_vector;
323 /* (-m) True means we're printing multiple files in parallel. */
324 static int parallel_files = FALSE;
326 /* (-m) True means a line starts with some empty columns (some files
327 already CLOSED or ON_HOLD) which we have to align. */
328 static int align_empty_cols;
330 /* (-m) True means we have not yet found any printable column in a line.
331 align_empty_cols = TRUE has to be maintained. */
332 static int empty_line;
334 /* (-m) False means printable column output precedes a form feed found.
335 Column align is done only once. No additional action with that form
336 feed.
337 True means we found only a form feed in a column. Maybe we have to do
338 some column align with that form feed. */
339 static int FF_only;
341 /* (-[0-9]+) True means we're given an option explicitly specifying
342 number of columns. Used to detect when this option is used with -m. */
343 static int explicit_columns = FALSE;
345 /* (-t|-T) False means we aren't printing headers and footers. */
346 static int extremities = TRUE;
348 /* (-t) True means we retain all FF set by hand in input files.
349 False is set with -T option. */
350 static int keep_FF = FALSE;
351 static int print_a_FF = FALSE;
353 /* True means we need to print a header as soon as we know we've got input
354 to print after it. */
355 static int print_a_header;
357 /* (-h) True means we're using the standard header rather than a
358 customized one specified by the -h flag. */
359 static int standard_header = TRUE;
361 /* (-f) True means use formfeeds instead of newlines to separate pages. */
362 static int use_form_feed = FALSE;
364 /* True means we have read the standard input. */
365 static int have_read_stdin = FALSE;
367 /* True means the -a flag has been given. */
368 static int print_across_flag = FALSE;
370 /* True means we're printing one file in multiple (>1) downward columns. */
371 static int storing_columns = TRUE;
373 /* (-b) True means balance columns on the last page as Sys V does. */
374 /* That's no longer an independent option. With storing_columns = TRUE
375 balance_columns = TRUE is used too (s. function init_parameters).
376 We get a consistent formulation with "FF set by hand" in input files. */
377 static int balance_columns = FALSE;
379 /* (-l) Number of lines on a page, including header and footer lines. */
380 static int lines_per_page = 66;
382 /* Number of lines in the header and footer can be reset to 0 using
383 the -t flag. */
384 static int lines_per_header = 5;
385 static int lines_per_body;
386 static int lines_per_footer = 5;
388 /* (-w) Width in characters of the page. Does not include the width of
389 the margin. */
390 static int chars_per_line = 72;
392 /* (-w) True means we truncate lines longer than chars_per_column. */
393 static int truncate_lines = FALSE;
395 /* (-j) True means we join lines without any line truncation. -j
396 dominates -w option. */
397 static int join_lines = FALSE;
399 /* Number of characters in a column. Based on col_sep_length and
400 page width. */
401 static int chars_per_column;
403 /* (-e) True means convert tabs to spaces on input. */
404 static int untabify_input = FALSE;
406 /* (-e) The input tab character. */
407 static char input_tab_char = '\t';
409 /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
410 where the leftmost column is 1. */
411 static int chars_per_input_tab = 8;
413 /* (-i) True means convert spaces to tabs on output. */
414 static int tabify_output = FALSE;
416 /* (-i) The output tab character. */
417 static char output_tab_char = '\t';
419 /* (-i) The width of the output tab. */
420 static int chars_per_output_tab = 8;
422 /* Keeps track of pending white space. When we hit a nonspace
423 character after some whitespace, we print whitespace, tabbing
424 if necessary to get to output_position + spaces_not_printed. */
425 static int spaces_not_printed;
427 /* (-o) Number of spaces in the left margin (tabs used when possible). */
428 static int chars_per_margin = 0;
430 /* Position where the next character will fall.
431 Leftmost position is 0 + chars_per_margin.
432 Rightmost position is chars_per_margin + chars_per_line - 1.
433 This is important for converting spaces to tabs on output. */
434 static int output_position;
436 /* Horizontal position relative to the current file.
437 (output_position depends on where we are on the page;
438 input_position depends on where we are in the file.)
439 Important for converting tabs to spaces on input. */
440 static int input_position;
442 /* Count number of failed opens so we can exit with nonzero
443 status if there were any. */
444 static int failed_opens = 0;
446 /* The number of spaces taken up if we print a tab character with width
447 c_ from position h_. */
448 #define TAB_WIDTH(c_, h_) ((c_) - ((h_) % (c_)))
450 /* The horizontal position we'll be at after printing a tab character
451 of width c_ from the position h_. */
452 #define POS_AFTER_TAB(c_, h_) ((h_) + TAB_WIDTH (c_, h_))
454 /* (-NNN) Number of columns of text to print. */
455 static int columns = 1;
457 /* (+NNN:MMM) Page numbers on which to begin and stop printing. */
458 static int first_page_number = 1;
459 static int last_page_number = 0;
461 /* Number of files open (not closed, not on hold). */
462 static int files_ready_to_read = 0;
464 /* Current page number. Displayed in header. */
465 static int page_number;
467 /* Current line number. Displayed when -n flag is specified.
469 When printing files in parallel (-m flag), line numbering is as follows:
470 1 foo goo moo
471 2 hoo too zoo
473 When printing files across (-a flag), ...
474 1 foo 2 moo 3 goo
475 4 hoo 3 too 6 zoo
477 Otherwise, line numbering is as follows:
478 1 foo 3 goo 5 too
479 2 moo 4 hoo 6 zoo */
480 static int line_number;
482 /* (-n) True means lines should be preceded by numbers. */
483 static int numbered_lines = FALSE;
485 /* (-n) Character which follows each line number. */
486 static char number_separator = '\t';
488 /* (-n) line counting starts with 1st line of input file (not with 1st
489 line of 1st page printed). */
490 static int line_count = 1;
492 /* (-n) True means counting of skipped lines starts with 1st line of
493 input file. False means -N option is used in addition, counting of
494 skipped lines not required. */
495 static int skip_count = TRUE;
497 /* (-N) Counting starts with start_line_number = NUMBER at 1st line of
498 first page printed, usually not 1st page of input file. */
499 static int start_line_num = 1;
501 /* (-n) Width in characters of a line number. */
502 static int chars_per_number = 5;
504 /* Used when widening the first column to accommodate numbers -- only
505 needed when printing files in parallel. Includes width of both the
506 number and the number_separator. */
507 static int number_width;
509 /* Buffer sprintf uses to format a line number. */
510 static char *number_buff;
512 /* (-v) True means unprintable characters are printed as escape sequences.
513 control-g becomes \007. */
514 static int use_esc_sequence = FALSE;
516 /* (-c) True means unprintable characters are printed as control prefixes.
517 control-g becomes ^G. */
518 static int use_cntrl_prefix = FALSE;
520 /* (-d) True means output is double spaced. */
521 static int double_space = FALSE;
523 /* Number of files opened initially in init_files. Should be 1
524 unless we're printing multiple files in parallel. */
525 static int total_files = 0;
527 /* (-r) True means don't complain if we can't open a file. */
528 static int ignore_failed_opens = FALSE;
530 /* (-s) True means we separate columns with a specified string.
531 -s option does not affect line truncation nor column alignment. */
532 static int use_col_separator = FALSE;
534 /* String used to separate columns if the -s option has been specified.
535 Default without -s but together with one of the column options
536 -a|COLUMN|-m is a `space' and with the -j option a `tab'. */
537 static char *col_sep_string;
538 static int col_sep_length = 0;
539 static char *column_separator = " ";
540 static char *line_separator = "\t";
542 /* Number of separator characters waiting to be printed as soon as we
543 know that we have any input remaining to be printed. */
544 static int separators_not_printed;
546 /* Position we need to pad to, as soon as we know that we have input
547 remaining to be printed. */
548 static int padding_not_printed;
550 /* True means we should pad the end of the page. Remains false until we
551 know we have a page to print. */
552 static int pad_vertically;
554 /* (-h) String of characters used in place of the filename in the header. */
555 static char *custom_header;
557 /* String containing the date, filename or custom header, and "Page ". */
558 static char *header;
560 static int *clump_buff;
562 /* If nonzero, display usage information and exit. */
563 static int show_help;
565 /* If nonzero, print the version on standard output then exit. */
566 static int show_version;
568 /* True means we read the line no. lines_per_body in skip_read
569 called by skip_to_page. That variable controls the coincidence of a
570 "FF set by hand" and "full_page_printed", see above the definition of
571 structure COLUMN. */
572 static int last_line = FALSE;
574 /* If nonzero, print a non-variable date and time with the header
575 -h HEADER using pr test-suite */
576 static int test_suite;
578 static struct option const long_options[] =
580 {"help", no_argument, &show_help, 1},
581 {"version", no_argument, &show_version, 1},
582 {"test", no_argument, &test_suite, 1},
583 {"pages", required_argument, NULL, CHAR_MAX + 1},
584 {"columns", required_argument, NULL, CHAR_MAX + 2},
585 {"across", no_argument, NULL, 'a'},
586 {"show-control-chars", no_argument, NULL, 'c'},
587 {"double-space", no_argument, NULL, 'd'},
588 {"expand-tabs", optional_argument, NULL, 'e'},
589 {"form-feed", no_argument, NULL, 'f'},
590 {"header", required_argument, NULL, 'h'},
591 {"output-tabs", optional_argument, NULL, 'i'},
592 {"join-lines", no_argument, NULL, 'j'},
593 {"length", required_argument, NULL, 'l'},
594 {"merge", no_argument, NULL, 'm'},
595 {"number-lines", optional_argument, NULL, 'n'},
596 {"first-line-number", required_argument, NULL, 'N'},
597 {"indent", required_argument, NULL, 'o'},
598 {"no-file-warnings", no_argument, NULL, 'r'},
599 {"separator", optional_argument, NULL, 's'},
600 {"omit-header", no_argument, NULL, 't'},
601 {"omit-pagination", no_argument, NULL, 'T'},
602 {"show-nonprinting", no_argument, NULL, 'v'},
603 {"width", required_argument, NULL, 'w'},
604 {0, 0, 0, 0}
607 /* Return the number of columns that have either an open file or
608 stored lines. */
610 static int
611 cols_ready_to_print (void)
613 COLUMN *q;
614 int i;
615 int n;
617 n = 0;
618 for (q = column_vector, i = 0; i < columns; ++q, ++i)
619 if (q->status == OPEN ||
620 q->status == FF_FOUND || /* With -b: To print a header only */
621 (storing_columns && q->lines_stored > 0 && q->lines_to_print > 0))
622 ++n;
623 return n;
626 /* Estimate first_ / last_page_number
627 using option +FIRST_PAGE:LAST_PAGE */
629 static void
630 first_last_page (char *pages)
632 char *str1;
634 if (*pages == ':')
636 error (0, 0, _("invalid range of page numbers: `%s'"), pages);
637 usage (2);
640 str1 = strchr (pages, ':');
641 if (str1 != NULL)
642 *str1 = '\0';
645 long int tmp_long;
646 if (xstrtol (pages, NULL, 10, &tmp_long, "") != LONGINT_OK
647 || tmp_long <= 0 || tmp_long > INT_MAX)
648 error (EXIT_FAILURE, 0, _("invalid starting page number: `%s'"),
649 pages);
650 first_page_number = (int) tmp_long;
653 if (str1 == NULL)
654 return;
657 long int tmp_long;
658 if (xstrtol (str1 + 1, NULL, 10, &tmp_long, "") != LONGINT_OK
659 || tmp_long <= 0 || tmp_long > INT_MAX)
660 error (EXIT_FAILURE, 0, _("invalid ending page number: `%s'"),
661 str1 + 1);
662 last_page_number = (int) tmp_long;
665 if (first_page_number > last_page_number)
666 error (EXIT_FAILURE, 0,
667 _("starting page number is larger than ending page number"));
670 /* Estimate length of col_sep_string with option -s[STRING] */
672 static void
673 separator_string (const char *optarg_S)
675 col_sep_length = (int) strlen (optarg_S);
676 col_sep_string = (char *) xmalloc (col_sep_length + 1);
677 strcpy (col_sep_string, optarg_S);
681 main (int argc, char **argv)
683 int c;
684 int accum = 0;
685 int n_files;
686 char **file_names;
688 program_name = argv[0];
689 setlocale (LC_ALL, "");
690 bindtextdomain (PACKAGE, LOCALEDIR);
691 textdomain (PACKAGE);
693 n_files = 0;
694 file_names = (argc > 1
695 ? (char **) xmalloc ((argc - 1) * sizeof (char *))
696 : NULL);
698 while (1)
700 c = getopt_long (argc, argv,
701 "-0123456789abcde::fFh:i::jl:mn::N:o:rs::tTvw:",
702 long_options, NULL);
703 if (c == 1) /* Non-option argument. */
705 char *s;
706 s = optarg;
707 if (*s == '+')
709 ++s;
710 first_last_page (s);
712 else
714 file_names[n_files++] = optarg;
717 else
719 if (ISDIGIT (c))
721 accum = accum * 10 + c - '0';
722 continue;
724 else
726 if (accum > 0)
728 columns = accum;
729 explicit_columns = TRUE;
730 accum = 0;
735 if (c == 1)
736 continue;
738 if (c == EOF)
739 break;
741 switch (c)
743 case 0: /* getopt long option */
744 break;
746 case CHAR_MAX + 1: /* --pages=FIRST_PAGE[:LAST_PAGE] */
747 first_last_page (optarg);
748 break;
750 case CHAR_MAX + 2: /* --columns=COLUMN */
752 long int tmp_long;
753 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
754 || tmp_long <= 0 || tmp_long > INT_MAX)
756 error (EXIT_FAILURE, 0,
757 _("`--columns=COLUMN' invalid number of columns: `%s'"),
758 optarg);
760 columns = (int) tmp_long;
761 break;
764 case 'a':
765 print_across_flag = TRUE;
766 storing_columns = FALSE;
767 break;
768 case 'b':
769 balance_columns = TRUE;
770 break;
771 case 'c':
772 use_cntrl_prefix = TRUE;
773 break;
774 case 'd':
775 double_space = TRUE;
776 break;
777 case 'e':
778 if (optarg)
779 getoptarg (optarg, 'e', &input_tab_char,
780 &chars_per_input_tab);
781 /* Could check tab width > 0. */
782 untabify_input = TRUE;
783 break;
784 case 'f':
785 case 'F':
786 use_form_feed = TRUE;
787 break;
788 case 'h':
789 custom_header = optarg;
790 standard_header = FALSE;
791 break;
792 case 'i':
793 if (optarg)
794 getoptarg (optarg, 'i', &output_tab_char,
795 &chars_per_output_tab);
796 /* Could check tab width > 0. */
797 tabify_output = TRUE;
798 break;
799 case 'j':
800 join_lines = TRUE;
801 break;
802 case 'l':
804 long int tmp_long;
805 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
806 || tmp_long <= 0 || tmp_long > INT_MAX)
808 error (EXIT_FAILURE, 0,
809 _("`-l PAGE_LENGTH' invalid number of lines: `%s'"),
810 optarg);
812 lines_per_page = (int) tmp_long;
813 break;
815 case 'm':
816 parallel_files = TRUE;
817 storing_columns = FALSE;
818 break;
819 case 'n':
820 numbered_lines = TRUE;
821 if (optarg)
822 getoptarg (optarg, 'n', &number_separator,
823 &chars_per_number);
824 break;
825 case 'N':
826 skip_count = FALSE;
828 long int tmp_long;
829 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
830 || tmp_long > INT_MAX)
832 error (EXIT_FAILURE, 0,
833 _("`-N NUMBER' invalid starting line number: `%s'"),
834 optarg);
836 start_line_num = (int) tmp_long;
837 break;
839 case 'o':
841 long int tmp_long;
842 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
843 || tmp_long < 0 || tmp_long > INT_MAX)
844 error (EXIT_FAILURE, 0,
845 _("`-o MARGIN' invalid line offset: `%s'"), optarg);
846 chars_per_margin = (int) tmp_long;
847 break;
849 case 'r':
850 ignore_failed_opens = TRUE;
851 break;
852 case 's':
853 use_col_separator = TRUE;
854 if (optarg)
855 separator_string (optarg);
856 break;
857 case 't':
858 extremities = FALSE;
859 keep_FF = TRUE;
860 break;
861 case 'T':
862 extremities = FALSE;
863 keep_FF = FALSE;
864 break;
865 case 'v':
866 use_esc_sequence = TRUE;
867 break;
868 case 'w':
869 truncate_lines = TRUE;
871 long int tmp_long;
872 if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
873 || tmp_long <= 0 || tmp_long > INT_MAX)
874 error (EXIT_FAILURE, 0,
875 _("`-w PAGE_WIDTH' invalid column number: `%s'"), optarg);
876 chars_per_line = (int) tmp_long;
877 break;
879 default:
880 usage (2);
881 break;
885 if (show_version)
887 printf ("pr (%s) %s\n", GNU_PACKAGE, VERSION);
888 exit (EXIT_SUCCESS);
891 if (show_help)
892 usage (0);
894 if (parallel_files && explicit_columns)
895 error (EXIT_FAILURE, 0,
896 _("Cannot specify number of columns when printing in parallel."));
898 if (parallel_files && print_across_flag)
899 error (EXIT_FAILURE, 0,
900 _("Cannot specify both printing across and printing in parallel."));
902 for (; optind < argc; optind++)
904 file_names[n_files++] = argv[optind];
907 if (n_files == 0)
909 /* No file arguments specified; read from standard input. */
910 print_files (0, NULL);
912 else
914 if (parallel_files)
915 print_files (n_files, file_names);
916 else
918 int i;
919 for (i = 0; i < n_files; i++)
920 print_files (1, &file_names[i]);
924 cleanup ();
926 if (have_read_stdin && fclose (stdin) == EOF)
927 error (EXIT_FAILURE, errno, _("standard input"));
928 if (ferror (stdout) || fclose (stdout) == EOF)
929 error (EXIT_FAILURE, errno, _("write error"));
930 if (failed_opens > 0)
931 exit (EXIT_FAILURE);
932 exit (EXIT_SUCCESS);
935 /* Parse options of the form -scNNN.
937 Example: -nck, where 'n' is the option, c is the optional number
938 separator, and k is the optional width of the field used when printing
939 a number. */
941 static void
942 getoptarg (char *arg, char switch_char, char *character, int *number)
944 if (!ISDIGIT (*arg))
945 *character = *arg++;
946 if (*arg)
948 long int tmp_long;
949 if (xstrtol (arg, NULL, 10, &tmp_long, "") != LONGINT_OK
950 || tmp_long <= 0 || tmp_long > INT_MAX)
952 error (0, 0,
953 _("`-%c' extra characters or invalid number in the argument: `%s'"),
954 switch_char, arg);
955 usage (2);
957 *number = (int) tmp_long;
961 /* Set parameters related to formatting. */
963 static void
964 init_parameters (int number_of_files)
966 int chars_used_by_number = 0;
968 if (use_form_feed)
970 lines_per_header = 3;
971 lines_per_footer = 0;
974 lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
975 if (lines_per_body <= 0)
977 extremities = FALSE;
978 keep_FF = TRUE;
980 if (extremities == FALSE)
981 lines_per_body = lines_per_page;
983 if (double_space)
984 lines_per_body = lines_per_body / 2;
986 /* If input is stdin, cannot print parallel files. BSD dumps core
987 on this. */
988 if (number_of_files == 0)
989 parallel_files = FALSE;
991 if (parallel_files)
992 columns = number_of_files;
994 /* One file, multi columns down: -b option is set to get a consistent
995 formulation with "FF set by hand" in input files. */
996 if (storing_columns)
997 balance_columns = TRUE;
999 /* Tabification is assumed for multiple columns. */
1000 if (columns > 1)
1002 if (!use_col_separator)
1004 /* Use default separator */
1005 if (join_lines)
1006 col_sep_string = line_separator;
1007 else
1008 col_sep_string = column_separator;
1009 col_sep_length = 1;
1010 use_col_separator = TRUE;
1013 truncate_lines = TRUE;
1014 untabify_input = TRUE;
1015 tabify_output = TRUE;
1017 else
1018 storing_columns = FALSE;
1020 /* -j dominates -w in any case */
1021 if (join_lines)
1022 truncate_lines = FALSE;
1024 if (numbered_lines)
1026 line_count = start_line_num;
1027 if (number_separator == input_tab_char)
1029 number_width = chars_per_number +
1030 TAB_WIDTH (chars_per_input_tab,
1031 (chars_per_margin + chars_per_number));
1033 else
1034 number_width = chars_per_number + 1;
1035 /* The number is part of the column width unless we are
1036 printing files in parallel. */
1037 if (parallel_files)
1038 chars_used_by_number = number_width;
1041 chars_per_column = (chars_per_line - chars_used_by_number -
1042 (columns - 1) * col_sep_length) / columns;
1044 if (chars_per_column < 1)
1045 error (EXIT_FAILURE, 0, _("page width too narrow"));
1047 if (numbered_lines)
1049 if (number_buff != NULL)
1050 free (number_buff);
1051 number_buff = (char *) xmalloc (2 * chars_per_number);
1054 /* Pick the maximum between the tab width and the width of an
1055 escape sequence. */
1056 if (clump_buff != NULL)
1057 free (clump_buff);
1058 clump_buff = (int *) xmalloc ((chars_per_input_tab > 4
1059 ? chars_per_input_tab : 4) * sizeof (int));
1062 /* Open the necessary files,
1063 maintaining a COLUMN structure for each column.
1065 With multiple files, each column p has a different p->fp.
1066 With single files, each column p has the same p->fp.
1067 Return 1 if (number_of_files > 0) and no files can be opened,
1068 0 otherwise.
1070 With each column/file p, p->full_page_printed is initialized,
1071 see also open_file. */
1073 static int
1074 init_fps (int number_of_files, char **av)
1076 int i, files_left;
1077 COLUMN *p;
1078 FILE *firstfp;
1079 char *firstname;
1081 total_files = 0;
1083 if (column_vector != NULLCOL)
1084 free ((char *) column_vector);
1085 column_vector = (COLUMN *) xmalloc (columns * sizeof (COLUMN));
1087 if (parallel_files)
1089 files_left = number_of_files;
1090 for (p = column_vector; files_left--; ++p, ++av)
1092 if (open_file (*av, p) == 0)
1094 --p;
1095 --columns;
1098 if (columns == 0)
1099 return 1;
1100 init_header ("", -1);
1102 else
1104 p = column_vector;
1105 if (number_of_files > 0)
1107 if (open_file (*av, p) == 0)
1108 return 1;
1109 init_header (*av, fileno (p->fp));
1110 p->lines_stored = 0;
1112 else
1114 p->name = _("standard input");
1115 p->fp = stdin;
1116 have_read_stdin = TRUE;
1117 p->status = OPEN;
1118 p->full_page_printed = FALSE;
1119 ++total_files;
1120 init_header ("", -1);
1121 p->lines_stored = 0;
1124 firstname = p->name;
1125 firstfp = p->fp;
1126 for (i = columns - 1, ++p; i; --i, ++p)
1128 p->name = firstname;
1129 p->fp = firstfp;
1130 p->status = OPEN;
1131 p->full_page_printed = FALSE;
1132 p->lines_stored = 0;
1135 files_ready_to_read = total_files;
1136 return 0;
1139 /* Determine print_func and char_func, the functions
1140 used by each column for printing and/or storing.
1142 Determine the horizontal position desired when we begin
1143 printing a column (p->start_position). */
1145 static void
1146 init_funcs (void)
1148 int i, h, h_next;
1149 COLUMN *p;
1151 h = chars_per_margin;
1153 if (!truncate_lines)
1154 h_next = ANYWHERE;
1155 else
1157 /* When numbering lines of parallel files, we enlarge the
1158 first column to accomodate the number. Looks better than
1159 the Sys V approach. */
1160 if (parallel_files && numbered_lines)
1161 h_next = h + chars_per_column + number_width;
1162 else
1163 h_next = h + chars_per_column;
1166 /* Enlarge p->start_position of first column to use the same form of
1167 padding_not_printed with all columns. */
1168 h = h + col_sep_length;
1170 /* This loop takes care of all but the rightmost column. */
1172 for (p = column_vector, i = 1; i < columns; ++p, ++i)
1174 if (storing_columns) /* One file, multi columns down. */
1176 p->char_func = store_char;
1177 p->print_func = print_stored;
1179 else
1180 /* One file, multi columns across; or parallel files. */
1182 p->char_func = print_char;
1183 p->print_func = read_line;
1186 /* Number only the first column when printing files in
1187 parallel. */
1188 p->numbered = numbered_lines && (!parallel_files || i == 1);
1189 p->start_position = h;
1191 /* If we don't truncate lines, all start_positions are
1192 ANYWHERE, except the first column's start_position when
1193 using a margin. */
1195 if (!truncate_lines)
1197 h = ANYWHERE;
1198 h_next = ANYWHERE;
1200 else
1202 h = h_next + col_sep_length;
1203 h_next = h + chars_per_column;
1207 /* The rightmost column.
1209 Doesn't need to be stored unless we intend to balance
1210 columns on the last page. */
1211 if (storing_columns && balance_columns)
1213 p->char_func = store_char;
1214 p->print_func = print_stored;
1216 else
1218 p->char_func = print_char;
1219 p->print_func = read_line;
1222 p->numbered = numbered_lines && (!parallel_files || i == 1);
1223 p->start_position = h;
1226 /* Open a file. Return nonzero if successful, zero if failed.
1228 With each file p, p->full_page_printed is initialized,
1229 see also init_fps. */
1231 static int
1232 open_file (char *name, COLUMN *p)
1234 if (STREQ (name, "-"))
1236 p->name = _("standard input");
1237 p->fp = stdin;
1238 have_read_stdin = 1;
1240 else
1242 p->name = name;
1243 p->fp = fopen (name, "r");
1245 if (p->fp == NULL)
1247 ++failed_opens;
1248 if (!ignore_failed_opens)
1249 error (0, errno, "%s", name);
1250 return 0;
1252 p->status = OPEN;
1253 p->full_page_printed = FALSE;
1254 ++total_files;
1255 return 1;
1258 /* Close the file in P.
1260 If we aren't dealing with multiple files in parallel, we change
1261 the status of all columns in the column list to reflect the close. */
1263 static void
1264 close_file (COLUMN *p)
1266 COLUMN *q;
1267 int i;
1269 if (p->status == CLOSED)
1270 return;
1271 if (ferror (p->fp))
1272 error (EXIT_FAILURE, errno, "%s", p->name);
1273 if (p->fp != stdin && fclose (p->fp) == EOF)
1274 error (EXIT_FAILURE, errno, "%s", p->name);
1276 if (!parallel_files)
1278 for (q = column_vector, i = columns; i; ++q, --i)
1280 q->status = CLOSED;
1281 if (q->lines_stored == 0)
1283 q->lines_to_print = 0;
1287 else
1289 p->status = CLOSED;
1290 p->lines_to_print = 0;
1293 --files_ready_to_read;
1296 /* Put a file on hold until we start a new page,
1297 since we've hit a form feed.
1299 If we aren't dealing with parallel files, we must change the
1300 status of all columns in the column list. */
1302 static void
1303 hold_file (COLUMN *p)
1305 COLUMN *q;
1306 int i;
1308 if (!parallel_files)
1309 for (q = column_vector, i = columns; i; ++q, --i)
1311 if (storing_columns)
1312 q->status = FF_FOUND;
1313 else
1314 q->status = ON_HOLD;
1316 else
1317 p->status = ON_HOLD;
1319 p->lines_to_print = 0;
1320 --files_ready_to_read;
1323 /* Undo hold_file -- go through the column list and change any
1324 ON_HOLD columns to OPEN. Used at the end of each page. */
1326 static void
1327 reset_status (void)
1329 int i = columns;
1330 COLUMN *p;
1332 for (p = column_vector; i; --i, ++p)
1333 if (p->status == ON_HOLD)
1335 p->status = OPEN;
1336 files_ready_to_read++;
1339 if (storing_columns)
1340 files_ready_to_read = 1;
1343 /* Print a single file, or multiple files in parallel.
1345 Set up the list of columns, opening the necessary files.
1346 Allocate space for storing columns, if necessary.
1347 Skip to first_page_number, if user has asked to skip leading pages.
1348 Determine which functions are appropriate to store/print lines
1349 in each column.
1350 Print the file(s). */
1352 static void
1353 print_files (int number_of_files, char **av)
1355 init_parameters (number_of_files);
1356 if (init_fps (number_of_files, av))
1357 return;
1358 if (storing_columns)
1359 init_store_cols ();
1361 if (first_page_number > 1)
1363 if (!skip_to_page (first_page_number))
1364 return;
1365 else
1366 page_number = first_page_number;
1368 else
1369 page_number = 1;
1371 init_funcs ();
1373 line_number = line_count;
1374 while (print_page ())
1378 /* Estimate the number of characters taken up by a short format date and
1379 time: "yy-mm-dd HH:MM" and: "Page NNNN". */
1380 #define CHARS_FOR_DATE_AND_PAGE 23
1382 /* Initialize header information.
1383 If DESC is non-negative, it is a file descriptor open to
1384 FILENAME for reading.
1386 Allocate space for a header string,
1387 Determine the time, insert file name or user-specified string.
1388 Make use of a centered header with left-hand-side truncation marked by
1389 a '*` in front, if necessary. */
1391 static void
1392 init_header (char *filename, int desc)
1394 int chars_per_middle, chars_free, lhs_blanks, rhs_blanks;
1395 char *f = filename;
1396 char *no_middle = "";
1397 char *header_text;
1398 struct tm *tmptr;
1399 struct stat st;
1400 char *datim = "- Date/Time --";
1402 if (filename == NULL)
1403 f = "";
1405 if (header != NULL)
1406 free (header);
1407 header = (char *) xmalloc (chars_per_line + 1);
1409 if (!standard_header && *custom_header == '\0')
1410 sprintf (header, "%s", " "); /* blank line header */
1411 else
1413 #define T_BUF_FMT "%Y-%m-%d %H:%M" /* date/time short format */
1414 #define T_BUF_SIZE 17 /* FIXME: using a literal here is fragile. */
1415 char t_buf[T_BUF_SIZE];
1417 /* If parallel files or standard input, use current time. */
1418 if (desc < 0 || STREQ (filename, "-") || fstat (desc, &st))
1419 st.st_mtime = time (NULL);
1421 tmptr = localtime (&st.st_mtime);
1422 strftime (t_buf, T_BUF_SIZE, T_BUF_FMT, tmptr);
1424 chars_per_middle = chars_per_line - CHARS_FOR_DATE_AND_PAGE;
1425 if (chars_per_middle < 3)
1427 header_text = no_middle; /* Nothing free for a heading */
1428 lhs_blanks = 1;
1429 rhs_blanks = 1;
1431 else
1433 header_text = standard_header ? f : custom_header;
1434 chars_free = chars_per_middle - (int) strlen (header_text);
1435 if (chars_free > 1)
1437 lhs_blanks = chars_free / 2; /* text not truncated */
1438 rhs_blanks = chars_free - lhs_blanks;
1440 else
1441 { /* lhs truncation */
1442 header_text = header_text - chars_free + 2;
1443 *header_text = '*';
1444 lhs_blanks = 1;
1445 rhs_blanks = 1;
1449 sprintf (header, _("%s%*s%s%*sPage"), (test_suite ? datim : t_buf),
1450 lhs_blanks, " ", header_text, rhs_blanks, " ");
1454 /* Set things up for printing a page
1456 Scan through the columns ...
1457 Determine which are ready to print
1458 (i.e., which have lines stored or open files)
1459 Set p->lines_to_print appropriately
1460 (to p->lines_stored if we're storing, or lines_per_body
1461 if we're reading straight from the file)
1462 Keep track of this total so we know when to stop printing */
1464 static void
1465 init_page (void)
1467 int j;
1468 COLUMN *p;
1470 if (storing_columns)
1472 store_columns ();
1473 for (j = columns - 1, p = column_vector; j; --j, ++p)
1475 p->lines_to_print = p->lines_stored;
1478 /* Last column. */
1479 if (balance_columns)
1481 p->lines_to_print = p->lines_stored;
1483 /* Since we're not balancing columns, we don't need to store
1484 the rightmost column. Read it straight from the file. */
1485 else
1487 if (p->status == OPEN)
1489 p->lines_to_print = lines_per_body;
1491 else
1492 p->lines_to_print = 0;
1495 else
1496 for (j = columns, p = column_vector; j; --j, ++p)
1497 if (p->status == OPEN)
1499 p->lines_to_print = lines_per_body;
1501 else
1502 p->lines_to_print = 0;
1505 /* Align empty columns and print separators.
1506 Empty columns will be formed by files with status ON_HOLD or CLOSED
1507 when printing multiple files in parallel. */
1509 static void
1510 align_column (COLUMN *p)
1512 padding_not_printed = p->start_position;
1513 if (padding_not_printed - col_sep_length > 0)
1515 pad_across_to (padding_not_printed - col_sep_length);
1516 padding_not_printed = ANYWHERE;
1519 if (use_col_separator)
1520 print_sep_string ();
1522 if (p->numbered)
1523 add_line_number (p);
1526 /* Print one page.
1528 As long as there are lines left on the page and columns ready to print,
1529 Scan across the column list
1530 if the column has stored lines or the file is open
1531 pad to the appropriate spot
1532 print the column
1533 pad the remainder of the page with \n or \f as requested
1534 reset the status of all files -- any files which where on hold because
1535 of formfeeds are now put back into the lineup. */
1537 static int
1538 print_page (void)
1540 int j;
1541 int lines_left_on_page;
1542 COLUMN *p;
1544 /* Used as an accumulator (with | operator) of successive values of
1545 pad_vertically. The trick is to set pad_vertically
1546 to zero before each run through the inner loop, then after that
1547 loop, it tells us whether a line was actually printed (whether a
1548 newline needs to be output -- or two for double spacing). But those
1549 values have to be accumulated (in pv) so we can invoke pad_down
1550 properly after the outer loop completes. */
1551 int pv;
1553 init_page ();
1555 if (cols_ready_to_print () == 0)
1556 return FALSE;
1558 if (extremities)
1559 print_a_header = TRUE;
1561 /* Don't pad unless we know a page was printed. */
1562 pad_vertically = FALSE;
1563 pv = FALSE;
1565 lines_left_on_page = lines_per_body;
1566 if (double_space)
1567 lines_left_on_page *= 2;
1569 while (lines_left_on_page > 0 && cols_ready_to_print () > 0)
1571 output_position = 0;
1572 spaces_not_printed = 0;
1573 separators_not_printed = 0;
1574 pad_vertically = FALSE;
1575 align_empty_cols = FALSE;
1576 empty_line = TRUE;
1578 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1580 input_position = 0;
1581 if (p->lines_to_print > 0 || p->status == FF_FOUND)
1583 FF_only = FALSE;
1584 padding_not_printed = p->start_position;
1585 if (!(p->print_func) (p))
1586 read_rest_of_line (p);
1587 pv |= pad_vertically;
1589 --p->lines_to_print;
1590 if (p->lines_to_print <= 0)
1592 if (cols_ready_to_print () <= 0)
1593 break;
1596 /* File p changed its status to ON_HOLD or CLOSED */
1597 if (parallel_files && p->status != OPEN)
1599 if (empty_line)
1600 align_empty_cols = TRUE;
1601 else if (p->status == CLOSED ||
1602 (p->status == ON_HOLD && FF_only))
1603 align_column (p);
1606 else if (parallel_files)
1608 /* File status ON_HOLD or CLOSED */
1609 if (empty_line)
1610 align_empty_cols = TRUE;
1611 else
1612 align_column (p);
1615 /* We need it also with an empty column */
1616 if (use_col_separator)
1617 ++separators_not_printed;
1620 if (pad_vertically)
1622 putchar ('\n');
1623 --lines_left_on_page;
1626 if (cols_ready_to_print () <= 0 && !extremities)
1627 break;
1629 if (double_space && pv)
1631 putchar ('\n');
1632 --lines_left_on_page;
1636 if (lines_left_on_page == 0)
1637 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1638 if (p->status == OPEN)
1639 p->full_page_printed = TRUE;
1641 pad_vertically = pv;
1643 if (pad_vertically && extremities)
1644 pad_down (lines_left_on_page + lines_per_footer);
1645 else if (keep_FF && print_a_FF)
1647 putchar ('\f');
1648 print_a_FF = FALSE;
1651 if (last_page_number && page_number > last_page_number)
1652 return FALSE; /* Stop printing with LAST_PAGE */
1654 reset_status (); /* Change ON_HOLD to OPEN. */
1656 return TRUE; /* More pages to go. */
1659 /* Allocate space for storing columns.
1661 This is necessary when printing multiple columns from a single file.
1662 Lines are stored consecutively in buff, separated by '\0'.
1664 The following doesn't apply any longer - any tuning possible?
1665 (We can't use a fixed offset since with the '-s' flag lines aren't
1666 truncated.)
1668 We maintain a list (line_vector) of pointers to the beginnings
1669 of lines in buff. We allocate one more than the number of lines
1670 because the last entry tells us the index of the last character,
1671 which we need to know in order to print the last line in buff. */
1673 static void
1674 init_store_cols (void)
1676 int total_lines = lines_per_body * columns;
1677 int chars_if_truncate = total_lines * (chars_per_column + 1);
1679 if (line_vector != NULL)
1680 free ((int *) line_vector);
1681 /* FIXME: here's where it was allocated. */
1682 line_vector = (int *) xmalloc ((total_lines + 1) * sizeof (int *));
1684 if (end_vector != NULL)
1685 free ((int *) end_vector);
1686 end_vector = (int *) xmalloc (total_lines * sizeof (int *));
1688 if (buff != NULL)
1689 free (buff);
1690 buff_allocated = (use_col_separator
1691 ? 2 * chars_if_truncate
1692 : chars_if_truncate); /* Tune this. */
1693 buff = (char *) xmalloc (buff_allocated);
1696 /* Store all but the rightmost column.
1697 (Used when printing a single file in multiple downward columns)
1699 For each column
1700 set p->current_line to be the index in line_vector of the
1701 first line in the column
1702 For each line in the column
1703 store the line in buff
1704 add to line_vector the index of the line's first char
1705 buff_start is the index in buff of the first character in the
1706 current line. */
1708 static void
1709 store_columns (void)
1711 int i, j;
1712 int line = 0;
1713 int buff_start;
1714 int last_col; /* The rightmost column which will be saved in buff */
1715 COLUMN *p;
1717 buff_current = 0;
1718 buff_start = 0;
1720 if (balance_columns)
1721 last_col = columns;
1722 else
1723 last_col = columns - 1;
1725 for (i = 1, p = column_vector; i <= last_col; ++i, ++p)
1726 p->lines_stored = 0;
1728 for (i = 1, p = column_vector; i <= last_col && files_ready_to_read;
1729 ++i, ++p)
1731 p->current_line = line;
1732 for (j = lines_per_body; j && files_ready_to_read; --j)
1734 if (p->status == OPEN) /* Redundant. Clean up. */
1736 input_position = 0;
1738 if (!read_line (p))
1739 read_rest_of_line (p);
1741 if (p->status == OPEN
1742 || buff_start != buff_current)
1744 ++p->lines_stored;
1745 line_vector[line] = buff_start;
1746 end_vector[line++] = input_position;
1747 buff_start = buff_current;
1752 /* Keep track of the location of the last char in buff. */
1753 line_vector[line] = buff_start;
1755 if (balance_columns && p->lines_stored != lines_per_body)
1756 balance (line);
1759 static void
1760 balance (int total_stored)
1762 COLUMN *p;
1763 int i, lines;
1764 int first_line = 0;
1766 for (i = 1, p = column_vector; i <= columns; ++i, ++p)
1768 lines = total_stored / columns;
1769 if (i <= total_stored % columns)
1770 ++lines;
1772 p->lines_stored = lines;
1773 p->current_line = first_line;
1775 first_line += lines;
1779 /* Store a character in the buffer. */
1781 static void
1782 store_char (int c)
1784 if (buff_current >= buff_allocated)
1786 /* May be too generous. */
1787 buff_allocated = 2 * buff_allocated;
1788 buff = (char *) xrealloc (buff, buff_allocated * sizeof (char));
1790 buff[buff_current++] = (char) c;
1793 static void
1794 add_line_number (COLUMN *p)
1796 int i;
1797 char *s;
1799 sprintf (number_buff, "%*d", chars_per_number, line_number++);
1800 s = number_buff;
1801 for (i = chars_per_number; i > 0; i--)
1802 (p->char_func) ((int) *s++);
1804 if (number_separator == input_tab_char)
1806 i = number_width - chars_per_number;
1807 while (i-- > 0)
1808 (p->char_func) ((int) ' ');
1810 else
1811 (p->char_func) ((int) number_separator);
1813 if (truncate_lines && !parallel_files)
1814 input_position += number_width;
1817 /* Print (or store) padding until the current horizontal position
1818 is position. */
1820 static void
1821 pad_across_to (int position)
1823 register int h = output_position;
1825 if (tabify_output)
1826 spaces_not_printed = position - output_position;
1827 else
1829 while (++h <= position)
1830 putchar (' ');
1831 output_position = position;
1835 /* Pad to the bottom of the page.
1837 If the user has requested a formfeed, use one.
1838 Otherwise, use newlines. */
1840 static void
1841 pad_down (int lines)
1843 register int i;
1845 if (use_form_feed)
1846 putchar ('\f');
1847 else
1848 for (i = lines; i; --i)
1849 putchar ('\n');
1852 /* Read the rest of the line.
1854 Read from the current column's file until an end of line is
1855 hit. Used when we've truncated a line and we no longer need
1856 to print or store its characters. */
1858 static void
1859 read_rest_of_line (COLUMN *p)
1861 register int c;
1862 FILE *f = p->fp;
1864 while ((c = getc (f)) != '\n')
1866 if (c == '\f')
1868 if ((c = getc (f)) != '\n')
1869 ungetc (c, f);
1870 if (keep_FF)
1871 print_a_FF = TRUE;
1872 hold_file (p);
1873 break;
1875 else if (c == EOF)
1877 close_file (p);
1878 break;
1883 /* Read a line with skip_to_page.
1885 Read from the current column's file until an end of line is
1886 hit. Used when we read full lines to skip pages.
1887 With skip_to_page we have to check for FF-coincidence which is done
1888 in function read_line otherwise.
1889 Count lines of skipped pages to find the line number of 1st page
1890 printed relative to 1st line of input file (start_line_num). */
1892 static void
1893 skip_read (COLUMN *p, int column_number)
1895 register int c;
1896 FILE *f = p->fp;
1897 int i, single_ff = FALSE;
1898 COLUMN *q;
1900 /* Read 1st character in a line or any character succeeding a FF */
1901 if ((c = getc (f)) == '\f' && p->full_page_printed)
1902 /* A FF-coincidence with a previous full_page_printed.
1903 To avoid an additional empty page, eliminate the FF */
1904 if ((c = getc (f)) == '\n')
1905 c = getc (f);
1907 p->full_page_printed = FALSE;
1909 /* 1st character a FF means a single FF without any printable
1910 characters. Don't count it as a line with -n option. */
1911 if (c == '\f')
1912 single_ff = TRUE;
1914 /* Preparing for a FF-coincidence: Maybe we finish that page
1915 without a FF found */
1916 if (last_line)
1917 p->full_page_printed = TRUE;
1919 while (c != '\n')
1921 if (c == '\f')
1923 /* No FF-coincidence possible,
1924 no catching up of a FF-coincidence with next page */
1925 if (last_line)
1927 if (!parallel_files)
1928 for (q = column_vector, i = columns; i; ++q, --i)
1929 q->full_page_printed = FALSE;
1930 else
1931 p->full_page_printed = FALSE;
1934 if ((c = getc (f)) != '\n')
1935 ungetc (c, f);
1936 hold_file (p);
1937 break;
1939 else if (c == EOF)
1941 close_file (p);
1942 break;
1944 c = getc (f);
1947 if (skip_count)
1948 if ((!parallel_files || column_number == 1) && !single_ff)
1949 ++line_count;
1952 /* If we're tabifying output,
1954 When print_char encounters white space it keeps track
1955 of our desired horizontal position and delays printing
1956 until this function is called. */
1958 static void
1959 print_white_space (void)
1961 register int h_new;
1962 register int h_old = output_position;
1963 register int goal = h_old + spaces_not_printed;
1965 while (goal - h_old > 1
1966 && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal)
1968 putchar (output_tab_char);
1969 h_old = h_new;
1971 while (++h_old <= goal)
1972 putchar (' ');
1974 output_position = goal;
1975 spaces_not_printed = 0;
1978 /* Print column separators.
1980 We keep a count until we know that we'll be printing a line,
1981 then print_sep_string() is called. */
1983 static void
1984 print_sep_string ()
1986 char *s;
1987 int l = col_sep_length;
1989 s = col_sep_string;
1991 if (spaces_not_printed > 0)
1992 print_white_space ();
1994 for (; separators_not_printed > 0; --separators_not_printed)
1996 while (l-- > 0)
1997 putchar (*s++);
1998 output_position += col_sep_length;
2002 /* Print (or store, depending on p->char_func) a clump of N
2003 characters. */
2005 static void
2006 print_clump (COLUMN *p, int n, int *clump)
2008 while (n--)
2009 (p->char_func) (*clump++);
2012 /* Print a character.
2014 Update the following comment: process-char hasn't been used any
2015 longer.
2016 If we're tabifying, all tabs have been converted to spaces by
2017 process_char(). Keep a count of consecutive spaces, and when
2018 a nonspace is encountered, call print_white_space() to print the
2019 required number of tabs and spaces. */
2021 static void
2022 print_char (int c)
2024 if (tabify_output)
2026 if (c == ' ')
2028 ++spaces_not_printed;
2029 return;
2031 else if (spaces_not_printed > 0)
2032 print_white_space ();
2034 /* Nonprintables are assumed to have width 0, except '\b'. */
2035 if (!ISPRINT (c))
2037 if (c == '\b')
2038 --output_position;
2040 else
2041 ++output_position;
2043 putchar (c);
2046 /* Skip to page PAGE before printing. */
2048 static int
2049 skip_to_page (int page)
2051 int n, i, j;
2052 COLUMN *p;
2054 for (n = 1; n < page; ++n)
2056 for (i = 1; i < lines_per_body; ++i)
2058 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2059 if (p->status == OPEN)
2060 skip_read (p, j);
2062 last_line = TRUE;
2063 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2064 if (p->status == OPEN)
2065 skip_read (p, j);
2067 if (storing_columns) /* change FF_FOUND to ON_HOLD */
2068 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
2069 p->status = ON_HOLD;
2071 reset_status ();
2072 last_line = FALSE;
2074 return files_ready_to_read > 0;
2077 /* Print a header.
2079 Formfeeds are assumed to use up two lines at the beginning of
2080 the page. */
2082 static void
2083 print_header (void)
2085 if (!use_form_feed)
2086 fprintf (stdout, "\n\n");
2088 output_position = 0;
2089 pad_across_to (chars_per_margin);
2090 print_white_space ();
2092 if (!standard_header && *custom_header == '\0')
2093 fprintf (stdout, "%s\n\n\n", header);
2094 else
2095 fprintf (stdout, "%s%5d\n\n\n", header, page_number++);
2097 print_a_header = FALSE;
2098 output_position = 0;
2101 /* Print (or store, if p->char_func is store_char()) a line.
2103 Read a character to determine whether we have a line or not.
2104 (We may hit EOF, \n, or \f)
2106 Once we know we have a line,
2107 set pad_vertically = TRUE, meaning it's safe
2108 to pad down at the end of the page, since we do have a page.
2109 print a header if needed.
2110 pad across to padding_not_printed if needed.
2111 print any separators which need to be printed.
2112 print a line number if it needs to be printed.
2114 Print the clump which corresponds to the first character.
2116 Enter a loop and keep printing until an end of line condition
2117 exists, or until we exceed chars_per_column.
2119 Return FALSE if we exceed chars_per_column before reading
2120 an end of line character, TRUE otherwise. */
2122 static int
2123 read_line (COLUMN *p)
2125 register int c, chars;
2126 int last_input_position;
2127 int j, k;
2128 COLUMN *q;
2130 /* Suppress `used before initialized' warning. */
2131 #ifdef lint
2132 chars = 0;
2133 #endif
2135 /* read 1st character in each line or any character succeeding a FF: */
2136 c = getc (p->fp);
2138 last_input_position = input_position;
2140 if (c == '\f' && p->full_page_printed)
2141 if ((c = getc (p->fp)) == '\n')
2142 c = getc (p->fp);
2143 p->full_page_printed = FALSE;
2145 switch (c)
2147 case '\f':
2148 if ((c = getc (p->fp)) != '\n')
2149 ungetc (c, p->fp);
2150 FF_only = TRUE;
2151 if (print_a_header && !storing_columns)
2153 pad_vertically = TRUE;
2154 print_header ();
2156 else if (keep_FF)
2157 print_a_FF = TRUE;
2158 hold_file (p);
2159 return TRUE;
2160 case EOF:
2161 close_file (p);
2162 return TRUE;
2163 case '\n':
2164 break;
2165 default:
2166 chars = char_to_clump (c);
2169 if (truncate_lines && input_position > chars_per_column)
2171 input_position = last_input_position;
2172 return FALSE;
2175 if (p->char_func != store_char)
2177 pad_vertically = TRUE;
2179 if (print_a_header && !storing_columns)
2180 print_header ();
2182 if (parallel_files && align_empty_cols)
2184 /* We have to align empty columns at the beginning of a line. */
2185 k = separators_not_printed;
2186 separators_not_printed = 0;
2187 for (j = 1, q = column_vector; j <= k; ++j, ++q)
2189 align_column (q);
2190 separators_not_printed += 1;
2192 padding_not_printed = p->start_position;
2193 if (truncate_lines)
2194 spaces_not_printed = chars_per_column;
2195 else
2196 spaces_not_printed = 0;
2197 align_empty_cols = FALSE;
2200 if (padding_not_printed - col_sep_length > 0)
2202 pad_across_to (padding_not_printed - col_sep_length);
2203 padding_not_printed = ANYWHERE;
2206 if (use_col_separator)
2207 print_sep_string ();
2210 if (p->numbered)
2211 add_line_number (p);
2213 empty_line = FALSE;
2214 if (c == '\n')
2215 return TRUE;
2217 print_clump (p, chars, clump_buff);
2219 for (;;)
2221 c = getc (p->fp);
2223 switch (c)
2225 case '\n':
2226 return TRUE;
2227 case '\f':
2228 if ((c = getc (p->fp)) != '\n')
2229 ungetc (c, p->fp);
2230 if (keep_FF)
2231 print_a_FF = TRUE;
2232 hold_file (p);
2233 return TRUE;
2234 case EOF:
2235 close_file (p);
2236 return TRUE;
2239 last_input_position = input_position;
2240 chars = char_to_clump (c);
2241 if (truncate_lines && input_position > chars_per_column)
2243 input_position = last_input_position;
2244 return FALSE;
2247 print_clump (p, chars, clump_buff);
2251 /* Print a line from buff.
2253 If this function has been called, we know we have "something to
2254 print". But it remains to be seen whether we have a real text page
2255 or an empty page (a single form feed) with/without a header only.
2256 Therefore first we set pad_vertically to TRUE and print a header
2257 if necessary.
2258 If FF_FOUND and we are using -t|-T option we omit any newline by
2259 setting pad_vertically to FALSE (see print_page).
2260 Otherwise we pad across if necessary, print separators if necessary
2261 and text of COLUMN *p.
2263 Return TRUE, meaning there is no need to call read_rest_of_line. */
2265 static int
2266 print_stored (COLUMN *p)
2268 COLUMN *q;
2269 int i;
2271 int line = p->current_line++;
2272 register char *first = &buff[line_vector[line]];
2273 /* FIXME
2274 UMR: Uninitialized memory read:
2275 * This is occurring while in:
2276 print_stored [pr.c:2239]
2277 * Reading 4 bytes from 0x5148c in the heap.
2278 * Address 0x5148c is 4 bytes into a malloc'd block at 0x51488 of 676 bytes
2279 * This block was allocated from:
2280 malloc [rtlib.o]
2281 xmalloc [xmalloc.c:94]
2282 init_store_cols [pr.c:1648]
2284 register char *last = &buff[line_vector[line + 1]];
2286 pad_vertically = TRUE;
2288 if (print_a_header)
2289 print_header ();
2291 if (p->status == FF_FOUND)
2293 for (i = 1, q = column_vector; i <= columns; ++i, ++q)
2294 q->status = ON_HOLD;
2295 if (column_vector->lines_to_print <= 0)
2297 if (!extremities)
2298 pad_vertically = FALSE;
2299 return TRUE; /* print a header only */
2303 if (padding_not_printed - col_sep_length > 0)
2305 pad_across_to (padding_not_printed - col_sep_length);
2306 padding_not_printed = ANYWHERE;
2309 if (use_col_separator)
2310 print_sep_string ();
2312 while (first != last)
2313 print_char (*first++);
2315 if (spaces_not_printed == 0)
2317 output_position = p->start_position + end_vector[line];
2318 if (p->start_position - col_sep_length == chars_per_margin)
2319 output_position -= col_sep_length;
2322 return TRUE;
2325 /* Convert a character to the proper format and return the number of
2326 characters in the resulting clump. Increment input_position by
2327 the width of the clump.
2329 Tabs are converted to clumps of spaces.
2330 Nonprintable characters may be converted to clumps of escape
2331 sequences or control prefixes.
2333 Note: the width of a clump is not necessarily equal to the number of
2334 characters in clump_buff. (e.g, the width of '\b' is -1, while the
2335 number of characters is 1.) */
2337 static int
2338 char_to_clump (int c)
2340 register int *s = clump_buff;
2341 register int i;
2342 char esc_buff[4];
2343 int width;
2344 int chars;
2346 if (c == input_tab_char)
2348 width = TAB_WIDTH (chars_per_input_tab, input_position);
2350 if (untabify_input)
2352 for (i = width; i; --i)
2353 *s++ = ' ';
2354 chars = width;
2356 else
2358 *s = c;
2359 chars = 1;
2363 else if (!ISPRINT (c))
2365 if (use_esc_sequence)
2367 width = 4;
2368 chars = 4;
2369 *s++ = '\\';
2370 sprintf (esc_buff, "%03o", c);
2371 for (i = 0; i <= 2; ++i)
2372 *s++ = (int) esc_buff[i];
2374 else if (use_cntrl_prefix)
2376 if (c < 0200)
2378 width = 2;
2379 chars = 2;
2380 *s++ = '^';
2381 *s++ = c ^ 0100;
2383 else
2385 width = 4;
2386 chars = 4;
2387 *s++ = '\\';
2388 sprintf (esc_buff, "%03o", c);
2389 for (i = 0; i <= 2; ++i)
2390 *s++ = (int) esc_buff[i];
2393 else if (c == '\b')
2395 width = -1;
2396 chars = 1;
2397 *s = c;
2399 else
2401 width = 0;
2402 chars = 1;
2403 *s = c;
2406 else
2408 width = 1;
2409 chars = 1;
2410 *s = c;
2413 input_position += width;
2414 return chars;
2417 /* We've just printed some files and need to clean up things before
2418 looking for more options and printing the next batch of files.
2420 Free everything we've xmalloc'ed, except `header'. */
2422 static void
2423 cleanup (void)
2425 if (number_buff)
2426 free (number_buff);
2427 if (clump_buff)
2428 free (clump_buff);
2429 if (column_vector)
2430 free (column_vector);
2431 if (line_vector)
2432 free (line_vector);
2433 if (end_vector)
2434 free (end_vector);
2435 if (buff)
2436 free (buff);
2439 /* Complain, print a usage message, and die. */
2441 static void
2442 usage (int status)
2444 if (status != 0)
2445 fprintf (stderr, _("Try `%s --help' for more information.\n"),
2446 program_name);
2447 else
2449 printf (_("\
2450 Usage: %s [OPTION]... [FILE]...\n\
2452 program_name);
2454 printf (_("\
2455 Paginate or columnate FILE(s) for printing.\n\
2457 +FIRST_PAGE[:LAST_PAGE]\n\
2458 --pages=FIRST_PAGE[:LAST_PAGE]\n\
2459 begin [stop] printing with page FIRST_[LAST_]PAGE\n\
2460 -COLUMN\n\
2461 --columns=COLUMN produce COLUMN-column output and print columns down,\n\
2462 unless -a is used. Balance number of lines in the\n\
2463 columns on each page.\n\
2464 -a, --across print columns across rather than down, used together\n\
2465 with -COLUMN\n\
2466 -c, --show-control-chars\n\
2467 use hat notation (^G) and octal backslash notation\n\
2468 -d, --double-space\n\
2469 double space the output\n\
2470 -e, --expand-tabs[=CHAR[WIDTH]]\n\
2471 expand input CHARs (TABs) to tab WIDTH (8)\n\
2472 -F, -f, --form-feed\n\
2473 use form feeds instead of newlines to separate pages\n\
2474 (by a 3-line page header with -f or a 5-line header\n\
2475 and trailer without -f)\n\
2476 -h, --header=HEADER\n\
2477 use a centered HEADER instead of filename in page headers\n\
2478 with long headers left-hand-side truncation may occur\n\
2479 -h \"\" prints a blank line. Don't use -h\"\"\n\
2480 -i, --output-tabs[=CHAR[WIDTH]]\n\
2481 replace spaces with CHARs (TABs) to tab WIDTH (8)\n\
2482 -j, --join-lines merge full lines, turns off -w line truncation, no column\n\
2483 alignment, -s[STRING] sets separators\n\
2484 -l, --length PAGE_LENGTH\n\
2485 set the page length to PAGE_LENGTH (66) lines\n\
2486 (default number of lines of text 56, with -f 63)\n"));
2487 printf (_("\
2488 -m, --merge print all files in parallel, one in each column,\n\
2489 truncate lines, but join lines of full length with -j\n\
2490 -n, --number-lines[=SEP[DIGITS]]\n\
2491 number lines, use DIGITS (5) digits, then SEP (TAB)\n\
2492 default counting starts with 1st line of input file\n\
2493 -N, --first-line-number=NUMBER\n\
2494 start counting with NUMBER at 1st line of first\n\
2495 page printed (see +FIRST_PAGE)\n\
2496 -o, --indent=MARGIN\n\
2497 offset each line with MARGIN spaces (do not affect -w)\n\
2498 -r, --no-file-warnings\n\
2499 inhibit warning when a file cannot be opened\n\
2500 -s, --separator[=STRING]\n\
2501 separate columns by an optional STRING, don't use\n\
2502 -s \"STRING\", -s only: No separator used (same as -s\"\"),\n\
2503 without -s: Default separator \'TAB\' with -j and \'space\'\n\
2504 otherwise (same as -s\" \")\n\
2505 -t, --omit-header inhibit page headers and trailers\n\
2506 -T, --omit-pagination\n\
2507 inhibit page headers and trailers, eliminate any page\n\
2508 layout by form feeds set in input files\n\
2509 -v, --show-nonprinting\n\
2510 use octal backslash notation\n\
2511 -w, --width=PAGE_WIDTH\n\
2512 set page width to PAGE_WIDTH (72) columns, truncate\n\
2513 lines (see also -j option)\n\
2514 --help display this help and exit\n\
2515 --version output version information and exit\n\
2517 -T implied by -l nn when nn <= 10 or <= 3 with -f. With no FILE, or when\n\
2518 FILE is -, read standard input.\n\
2519 "));
2520 puts (_("\nReport bugs to <bug-textutils@gnu.org>."));
2522 exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);