386BSD 0.1 development
[unix-history] / usr / src / usr.bin / pr / pr.c
CommitLineData
c9a30ac1
WJ
1/* pr -- convert text files for printing.
2 Copyright (C) 1988, 1991 Free Software Foundation, Inc.
3
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.
8
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.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18/* Author: Pete TerMaat. */
19\f
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
24
25 Ideas:
26
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.
29
30 Improve the printing of control prefixes.
31
32
33 Options:
34
35 +PAGE Begin output at page PAGE of the output.
36
37 -COLUMN Produce output that is COLUMN columns wide and print
38 columns down.
39
40 -a Print columns across rather than down. The input
41 one
42 two
43 three
44 four
45 will be printed as
46 one two three
47 four
48
49 -b Balance columns on the last page.
50
51 -c Print unprintable characters as control prefixes.
52 Control-g is printed as ^G.
53
54 -d Double space the output.
55
56 -e[c[k]] Expand tabs to spaces on input. Optional argument C
57 is the input tab character. (Default is `\t'.) Optional
58 argument K is the input tab character's width. (Default is 8.)
59
60 -F
61 -f Use formfeeds instead of newlines to separate pages.
62
63 -h header Replace the filename in the header with the string HEADER.
64
65 -i[c[k]] Replace spaces with tabs on output. Optional argument
66 C is the output tab character. (Default is `\t'.) Optional
67 argument K is the output tab character's width. (Default
68 is 8.)
69
70 -l lines Set the page length to LINES. Default is 66.
71
72 -m Print files in parallel.
73
74 -n[c[k]] Precede each column with a line number.
75 (With parallel files, precede each line with a line
76 number.) Optional argument C is the character to print
77 after each number. (Default `\t'.) Optional argument
78 K is the number of digits per line number. (Default 5.)
79
80 -o offset Offset each line with a margin OFFSET spaces wide.
81 Total page width is the size of this offset plus the
82 width set with `-w'.
83
84 -r Ignore files that can't be opened.
85
86 -s[c] Separate each line with a character. Optional argument C is
87 the character to be used. Default is `\t'.
88
89 -t Do not print headers or footers.
90
91 -v Print unprintable characters as escape sequences.
92 Control-G becomes \007.
93
94 -w width Set the page width to WIDTH characters. */
95\f
96#include <stdio.h>
97/*#include "getopt.h"*/
98#include <ctype.h>
99#include <sys/types.h>
100#include <time.h>
101#include <sys/stat.h>
102#include <unistd.h>
103#include <string.h>
104#include <errno.h>
105#include <stdlib.h>
106#include <fcntl.h>
107
108#ifdef isascii
109#define ISPRINT(c) (isascii (c) && isprint (c))
110#define ISDIGIT(c) (isascii (c) && isdigit (c))
111#else
112#define ISPRINT(c) isprint (c)
113#define ISDIGIT(c) isdigit (c)
114#endif
115
116int char_to_clump ();
117int read_line ();
118int print_page ();
119int print_stored ();
120void error (int, int, char *, ...);
121int open_file ();
122int skip_to_page ();
123void getoptarg ();
124void usage ();
125void print_files ();
126void init_header ();
127void init_store_cols ();
128void store_columns ();
129void balance ();
130void store_char ();
131void pad_down ();
132void read_rest_of_line ();
133void print_char ();
134void cleanup ();
135
136#ifndef TRUE
137#define TRUE 1
138#define FALSE 0
139#endif
140
141/* Used with start_position in the struct COLUMN described below.
142 If start_position == ANYWHERE, we aren't truncating columns and
143 can begin printing a column anywhere. Otherwise we must pad to
144 the horizontal position start_position. */
145#define ANYWHERE 0
146
147/* Each column has one of these structures allocated for it.
148 If we're only dealing with one file, fp is the same for all
149 columns.
150
151 The general strategy is to spend time setting up these column
152 structures (storing columns if necessary), after which printing
153 is a matter of flitting from column to column and calling
154 print_func.
155
156 Parallel files, single files printing across in multiple
157 columns, and single files printing down in multiple columns all
158 fit the same printing loop.
159
160 print_func Function used to print lines in this column.
161 If we're storing this column it will be
162 print_stored(), Otherwise it will be read_line().
163
164 char_func Function used to process characters in this column.
165 If we're storing this column it will be store_char(),
166 otherwise it will be print_char().
167
168 current_line Index of the current entry in line_vector, which
169 contains the index of the first character of the
170 current line in buff[].
171
172 lines_stored Number of lines in this column which are stored in
173 buff.
174
175 lines_to_print If we're storing this column, lines_to_print is
176 the number of stored_lines which remain to be
177 printed. Otherwise it is the number of lines
178 we can print without exceeding lines_per_body.
179
180 start_position The horizontal position we want to be in before we
181 print the first character in this column.
182
183 numbered True means precede this column with a line number. */
184
185typedef struct
186{
187 FILE *fp; /* File pointer for this column. */
188 enum
189 {
190 OPEN,
191 ON_HOLD, /* Hit a form feed. */
192 CLOSED
193 } status; /* Status of the file pointer. */
194 int (*print_func) (); /* Func to print lines in this col. */
195 void (*char_func) (); /* Func to print/store chars in this col. */
196 int current_line; /* Index of current place in line_vector. */
197 int lines_stored; /* Number of lines stored in buff. */
198 int lines_to_print; /* No. lines stored or space left on page. */
199 int start_position; /* Horizontal position of first char. */
200 int numbered;
201} COLUMN;
202
203#define NULLCOL (COLUMN *)0
204
205COLUMN *column_vector;
206
207/* When printing a single file in multiple downward columns,
208 we store the leftmost columns contiguously in buff.
209 To print a line from buff, get the index of the first char
210 from line_vector[i], and print up to line_vector[i+1]. */
211char *buff;
212
213/* Index of the position in buff where the next character
214 will be stored. */
215int buff_current;
216
217/* The number of characters in buff.
218 Used for allocation of buff and to detect overflow of buff. */
219int chars_per_buff;
220
221/* Array of indices into buff.
222 Each entry is an index of the first character of a line.
223 This is used when storing lines to facilitate shuffling when
224 we do column balancing on the last page. */
225int *line_vector;
226
227/* Array of horizonal positions.
228 For each line in line_vector, end_vector[line] is the horizontal
229 position we are in after printing that line. We keep track of this
230 so that we know how much we need to pad to prepare for the next
231 column. */
232int *end_vector;
233
234/* (-m) True means we're printing multiple files in parallel. */
235int parallel_files = FALSE;
236
237/* (-[0-9]+) True when we're given an option explicitly specifying
238 number of columns. Used to detect when this option is used with -m. */
239int explicit_columns = FALSE;
240
241/* (-t) True means we're printing headers and footers. */
242int extremities = TRUE;
243
244/* True means we need to print a header as soon as we know we've got input
245 to print after it. */
246int print_a_header;
247
248/* (-h) True means we're using the standard header rather than a
249 customized one specified by the -h flag. */
250int standard_header = TRUE;
251
252/* (-f) True means use formfeeds instead of newlines to separate pages. */
253int use_form_feed = FALSE;
254
255/* True means we haven't encountered any filenames in the argument list. */
256int input_is_stdin = TRUE;
257
258/* True means we have read the standard input. */
259int have_read_stdin = FALSE;
260
261/* True means the -a flag has been given. */
262int print_across_flag = FALSE;
263
264/* True means we're printing one file in multiple (>1) downward columns. */
265int storing_columns = TRUE;
266
267/* (-b) True means balance columns on the last page as Sys V does. */
268int balance_columns = FALSE;
269
270/* (-l) Number of lines on a page, including header and footer lines. */
271int lines_per_page = 66;
272
273/* Number of lines in the header and footer can be reset to 0 using
274 the -t flag. */
275int lines_per_header = 5;
276int lines_per_body;
277int lines_per_footer = 5;
278
279/* (-w) Width in characters of the page. Does not include the width of
280 the margin. */
281int chars_per_line = 72;
282
283/* Number of characters in a column. Based on the gutter and page widths. */
284int chars_per_column;
285
286/* (-e) True means convert tabs to spaces on input. */
287int untabify_input = FALSE;
288
289/* (-e) The input tab character. */
290char input_tab_char = '\t';
291
292/* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
293 where the leftmost column is 1. */
294int chars_per_input_tab = 8;
295
296/* (-i) True means convert spaces to tabs on output. */
297int tabify_output = FALSE;
298
299/* (-i) The output tab character. */
300char output_tab_char = '\t';
301
302/* (-i) The width of the output tab. */
303int chars_per_output_tab = 8;
304
305/* This is used to keep track of white space. When we hit a
306 nonspace character after some whitespace, we print whitespace, tabbing
307 if necessary to get to output_position + spaces_not_printed. */
308int spaces_not_printed;
309
310/* Number of spaces between columns (though tabs can be used when possible to
311 use up the equivalent amount of space). Not sure if this is worth making
312 a flag for. BSD uses 0, Sys V uses 1. Sys V looks better. */
313int chars_per_gutter = 1;
314
315/* (-o) Number of spaces in the left margin (tabs used when possible). */
316int chars_per_margin = 0;
317
318/* Position where the next character will fall.
319 Leftmost position is 0 + chars_per_margin.
320 Rightmost position is chars_per_margin + chars_per_line - 1
321 This is important for converting spaces to tabs on output. */
322int output_position;
323
324/* Horizontal position relative to the current file.
325 (output_position depends on where we are on the page;
326 input_position depends on where we are in the file.)
327 Important for converting tabs to spaces on input. */
328int input_position;
329
330/* Count number of failed opens so we can exit with non-zero
331 status if there were any. */
332int failed_opens = 0;
333
334/* The horizontal position we'll be at after printing a tab character
335 of width c_ from the position h_. */
336#define pos_after_tab(c_,h_) h_ - h_ % c_ + c_
337
338/* The number of spaces taken up if we print a tab character with width
339 c_ from position h_. */
340#define tab_width(c_,h_) - h_ % c_ + c_
341
342/* (-NNN) Number of columns of text to print. */
343int columns = 1;
344
345/* (+NNN) Page number on which to begin printing. */
346int first_page = 1;
347
348/* Number of files open (not closed, not on hold). */
349int ready_to_read = 0;
350
351/* Number of columns with either an open file or stored lines. */
352int ready_to_print = 0;
353
354/* Current page number. Displayed in header. */
355int page_number;
356
357/* Current line number. Displayed when -n flag is specified.
358
359 When printing files in parallel (-m flag), line numbering is as follows:
360 1 foo goo moo
361 2 hoo too zoo
362
363 When printing files across (-a flag), ...
364 1 foo 2 moo 3 goo
365 4 hoo 3 too 6 zoo
366
367 Otherwise, line numbering is as follows:
368 1 foo 3 goo 5 too
369 2 moo 4 hoo 6 zoo */
370int line_number;
371
372/* (-n) True means lines should be preceded by numbers. */
373int numbered_lines = FALSE;
374
375/* True means print a number as soon as we know we'll be printing
376 from the current column. */
377int print_a_number;
378
379/* (-n) Character which follows each line number. */
380char number_separator = '\t';
381
382/* (-n) Width in characters of a line number. */
383int chars_per_number = 5;
384
385/* Used when widening the first column to accommodate numbers -- only
386 needed when printing files in parallel. Includes width of both the
387 number and the number_separator. */
388int number_width;
389
390/* Buffer sprintf uses to format a line number. */
391char *number_buff;
392
393/* (-v) True means unprintable characters are printed as escape sequences.
394 control-g becomes \007. */
395int use_esc_sequence = FALSE;
396
397/* (-c) True means unprintable characters are printed as control prefixes.
398 control-g becomes ^G. */
399int use_cntrl_prefix = FALSE;
400
401/* (-d) True means output is double spaced. */
402int double_space = FALSE;
403
404/* Number of files opened initially in init_files(). Should be one
405 unless we're printing multiple files in parallel. */
406int total_files = 0;
407
408/* (-r) True means don't complain if we can't open a file. */
409int ignore_failed_opens = FALSE;
410
411/* (-s) True means we separate columns with a specified character. */
412int use_column_separator = FALSE;
413
414/* Character used to separate columns if the the -s flag has been specified. */
415char column_separator = '\t';
416
417/* Number of separator characters waiting to be printed as soon as we know
418 that we have any input remaining to be printed. */
419int separators_not_printed;
420
421/* Position we need to pad to, as soon as we know that we have input
422 remaining to be printed. */
423int padding_not_printed;
424
425/* True means we should pad the end of the page. Remains false until we
426 know we have a page to print. */
427int print_vertical_padding;
428
429/* (-h) String of characters used in place of the filename in the header. */
430char *custom_header;
431
432/* String containing the date, filename or custom header, and "Page ". */
433char *header;
434
435int *clump_buff;
436
437/* True means we truncate lines longer than chars_per_column. */
438int truncate_lines = FALSE;
439
440/* The name under which this program was invoked. */
441char *program_name;
442\f
443void
444main (argc, argv)
445 int argc;
446 char **argv;
447{
448 int c;
449 char *s;
450 int files = 0;
451 char **file_names, **file_name_vector;
452 int accum = 0;
453
454 program_name = argv[0];
455
456 file_name_vector = (char **) malloc (argc * sizeof (char **));
457 file_names = file_name_vector;
458
459 for (;;)
460 {
461 c = getopt (argc, argv, "-0123456789abcde::fFh:i::l:mn::o:rs::tvw:");
462
463 if (c == 1) /* Non-option argument. */
464 {
465 s = optarg;
466 if (*s == '+')
467 {
468 if (!ISDIGIT (*++s))
469 usage ("`+' requires a numeric argument");
470 first_page = atoi (s);
471 }
472 else
473 {
474 *file_names++ = optarg;
475 ++files;
476 }
477 }
478 else if (files > 0)
479 {
480 if (parallel_files && explicit_columns)
481 error (1, 0,
482"Cannot specify number of columns when printing in parallel.");
483
484 if (parallel_files && print_across_flag)
485 error (1, 0,
486"Cannot specify both printing across and printing in parallel.");
487
488 if (parallel_files)
489 print_files (files, file_name_vector);
490 else
491 {
492 file_names = file_name_vector;
493 while (files--)
494 print_files (1, file_names++);
495 }
496
497 input_is_stdin = FALSE;
498 file_names = file_name_vector;
499 files = 0;
500 cleanup ();
501 }
502
503 if (ISDIGIT (c))
504 {
505 accum = accum * 10 + c - '0';
506 continue;
507 }
508 else
509 {
510 if (accum > 0)
511 {
512 columns = accum;
513 explicit_columns = TRUE;
514 }
515 accum = 0;
516 }
517
518 switch (c)
519 {
520 case 'a':
521 print_across_flag = TRUE;
522 storing_columns = FALSE;
523 break;
524 case 'b':
525 balance_columns = TRUE;
526 break;
527 case 'c':
528 use_cntrl_prefix = TRUE;
529 break;
530 case 'd':
531 double_space = TRUE;
532 break;
533 case 'e':
534 if (optarg)
535 getoptarg (optarg, 'e', &input_tab_char,
536 &chars_per_input_tab);
537 /* Could check tab width > 0. */
538 untabify_input = TRUE;
539 break;
540 case 'f':
541 case 'F':
542 use_form_feed = TRUE;
543 break;
544 case 'h':
545 custom_header = optarg;
546 standard_header = FALSE;
547 break;
548 case 'i':
549 if (optarg)
550 getoptarg (optarg, 'i', &output_tab_char,
551 &chars_per_output_tab);
552 /* Could check tab width > 0. */
553 tabify_output = TRUE;
554 break;
555 case 'l':
556 lines_per_page = atoi (optarg);
557 break;
558 case 'm':
559 parallel_files = TRUE;
560 storing_columns = FALSE;
561 break;
562 case 'n':
563 numbered_lines = TRUE;
564 if (optarg)
565 getoptarg (optarg, 'n', &number_separator,
566 &chars_per_number);
567 break;
568 case 'o':
569 chars_per_margin = atoi (optarg);
570 break;
571 case 'r':
572 ignore_failed_opens = TRUE;
573 break;
574 case 's':
575 use_column_separator = TRUE;
576 if (optarg)
577 {
578 s = optarg;
579 column_separator = *s;
580 if (*++s)
581 {
582 fprintf (stderr, "\
583%s: extra characters in the argument to the `-s' option: `%s'\n",
584 program_name, s);
585 usage ((char *) 0);
586 }
587 }
588 break;
589 case 't':
590 extremities = FALSE;
591 break;
592 case 'v':
593 use_esc_sequence = TRUE;
594 break;
595 case 'w':
596 chars_per_line = atoi (optarg);
597 break;
598 case '?':
599 usage ((char *) 0);
600 break;
601 }
602
603 if (c == EOF)
604 break;
605 }
606
607 if (input_is_stdin)
608 print_files (0, (char **) 0);
609
610 if (have_read_stdin && fclose (stdin) == EOF)
611 error (1, errno, "-");
612 if (ferror (stdout) || fclose (stdout) == EOF)
613 error (1, errno, "write error");
614 if (failed_opens > 0)
615 exit(1);
616 exit (0);
617}
618
619/* Parse options of the form -scNNN.
620
621 Example: -nck, where 'n' is the option, c is the optional number
622 separator, and k is the optional width of the field used when printing
623 a number. */
624
625void
626getoptarg (arg, switch_char, character, number)
627 char *arg, switch_char, *character;
628 int *number;
629{
630 if (!ISDIGIT (*arg))
631 *character = *arg++;
632 if (*arg)
633 {
634 if (ISDIGIT (*arg))
635 *number = atoi (arg);
636 else
637 {
638 fprintf (stderr, "\
639%s: extra characters in the argument to the `-%c' option: `%s'\n",
640 program_name, switch_char, arg);
641 usage ((char *) 0);
642 }
643 }
644}
645\f
646/* Set parameters related to formatting. */
647
648void
649init_parameters (number_of_files)
650 int number_of_files;
651{
652 int chars_used_by_number = 0;
653
654 lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
655 if (lines_per_body <= 0)
656 extremities = FALSE;
657 if (extremities == FALSE)
658 lines_per_body = lines_per_page;
659
660 if (double_space)
661 lines_per_body = lines_per_body / 2;
662
663 /* If input is stdin, cannot print parallel files. BSD dumps core
664 on this. */
665 if (number_of_files == 0)
666 parallel_files = FALSE;
667
668 if (parallel_files)
669 columns = number_of_files;
670
671 /* Tabification is assumed for multiple columns. */
672 if (columns > 1)
673 {
674 if (!use_column_separator)
675 truncate_lines = TRUE;
676
677 untabify_input = TRUE;
678 tabify_output = TRUE;
679 }
680 else
681 storing_columns = FALSE;
682
683 if (numbered_lines)
684 {
685 if (number_separator == input_tab_char)
686 {
687 number_width = chars_per_number +
688 tab_width (chars_per_input_tab,
689 (chars_per_margin + chars_per_number));
690 }
691 else
692 number_width = chars_per_number + 1;
693 /* The number is part of the column width unless we are
694 printing files in parallel. */
695 if (parallel_files)
696 chars_used_by_number = number_width;
697 }
698
699 chars_per_column = (chars_per_line - chars_used_by_number -
700 (columns - 1) * chars_per_gutter) / columns;
701
702 if (chars_per_column < 1)
703 error (1, 0, "page width too narrow");
704
705 if (numbered_lines)
706 {
707 if (number_buff != (char *) 0)
708 free (number_buff);
709 number_buff = (char *)
710 malloc (2 * chars_per_number * sizeof (char));
711 }
712
713 /* Pick the maximum between the tab width and the width of an
714 escape sequence. */
715 if (clump_buff != (int *) 0)
716 free (clump_buff);
717 clump_buff = (int *) malloc ((chars_per_input_tab > 4
718 ? chars_per_input_tab : 4) * sizeof (int));
719}
720\f
721/* Open the necessary files,
722 maintaining a COLUMN structure for each column.
723
724 With multiple files, each column p has a different p->fp.
725 With single files, each column p has the same p->fp.
726 Return 1 if (number_of_files > 0) and no files can be opened,
727 0 otherwise. */
728
729int
730init_fps (number_of_files, av)
731 int number_of_files;
732 char **av;
733{
734 int i, files_left;
735 COLUMN *p;
736 FILE *firstfp;
737
738 total_files = 0;
739
740 if (column_vector != NULLCOL)
741 free ((char *) column_vector);
742 column_vector = (COLUMN *) malloc (columns * sizeof (COLUMN));
743
744 if (parallel_files)
745 {
746 files_left = number_of_files;
747 for (p = column_vector; files_left--; ++p, ++av)
748 {
749 if (open_file (*av, p) == 0)
750 {
751 --p;
752 --columns;
753 }
754 }
755 if (columns == 0)
756 return 1;
757 init_header ("", -1);
758 }
759 else
760 {
761 p = column_vector;
762 if (number_of_files > 0)
763 {
764 if (open_file (*av, p) == 0)
765 return 1;
766 init_header (*av, fileno (p->fp));
767 }
768 else
769 {
770 p->fp = stdin;
771 have_read_stdin = TRUE;
772 p->status = OPEN;
773 ++total_files;
774 init_header ("", -1);
775 }
776
777 firstfp = p->fp;
778 for (i = columns - 1, ++p; i; --i, ++p)
779 {
780 p->fp = firstfp;
781 p->status = OPEN;
782 }
783 }
784 ready_to_read = total_files;
785 return 0;
786}
787\f
788/* Determine print_func and char_func, the functions
789 used by each column for printing and/or storing.
790
791 Determine the horizontal position desired when we begin
792 printing a column (p->start_position). */
793
794void
795init_funcs ()
796{
797 int i, h, h_next;
798 COLUMN *p;
799
800 h = chars_per_margin;
801
802 if (use_column_separator)
803 h_next = ANYWHERE;
804 else
805 {
806 /* When numbering lines of parallel files, we enlarge the
807 first column to accomodate the number. Looks better than
808 the Sys V approach. */
809 if (parallel_files && numbered_lines)
810 h_next = h + chars_per_column + number_width;
811 else
812 h_next = h + chars_per_column;
813 }
814
815 /* This loop takes care of all but the rightmost column. */
816
817 for (p = column_vector, i = 1; i < columns; ++p, ++i)
818 {
819 if (storing_columns) /* One file, multi columns down. */
820 {
821 p->char_func = store_char;
822 p->print_func = print_stored;
823 }
824 else
825 /* One file, multi columns across; or parallel files. */
826 {
827 p->char_func = print_char;
828 p->print_func = read_line;
829 }
830
831 /* Number only the first column when printing files in
832 parallel. */
833 p->numbered = numbered_lines && (!parallel_files || i == 1);
834 p->start_position = h;
835
836 /* If we're using separators, all start_positions are
837 ANYWHERE, except the first column's start_position when
838 using a margin. */
839
840 if (use_column_separator)
841 {
842 h = ANYWHERE;
843 h_next = ANYWHERE;
844 }
845 else
846 {
847 h = h_next + chars_per_gutter;
848 h_next = h + chars_per_column;
849 }
850 }
851
852 /* The rightmost column.
853
854 Doesn't need to be stored unless we intend to balance
855 columns on the last page. */
856 if (storing_columns && balance_columns)
857 {
858 p->char_func = store_char;
859 p->print_func = print_stored;
860 }
861 else
862 {
863 p->char_func = print_char;
864 p->print_func = read_line;
865 }
866
867 p->numbered = numbered_lines && (!parallel_files || i == 1);
868 p->start_position = h;
869}
870\f
871/* Open a file. Return nonzero if successful, zero if failed. */
872
873int
874open_file (name, p)
875 char *name;
876 COLUMN *p;
877{
878 if (!strcmp (name, "-"))
879 {
880 p->fp = stdin;
881 have_read_stdin = 1;
882 }
883 else
884 p->fp = fopen (name, "r");
885 if (p->fp == NULL)
886 {
887 ++failed_opens;
888 if (!ignore_failed_opens)
889 error (0, errno, "%s", name);
890 return 0;
891 }
892 p->status = OPEN;
893 ++total_files;
894 return 1;
895}
896
897/* Close the file in P.
898
899 If we aren't dealing with multiple files in parallel, we change
900 the status of all columns in the column list to reflect the close. */
901
902void
903close_file (p)
904 COLUMN *p;
905{
906 COLUMN *q;
907 int i;
908
909 if (p->status == CLOSED)
910 return;
911 if (ferror (p->fp))
912 error (1, errno, "read error"); /* Where's that filename kept? */
913 if (p->fp != stdin && fclose (p->fp) == EOF)
914 error (1, errno, "read error"); /* Where's that filename kept? */
915
916 if (!parallel_files)
917 {
918 for (q = column_vector, i = columns; i; ++q, --i)
919 {
920 q->status = CLOSED;
921 if (q->lines_stored == 0)
922 {
923 if (ready_to_print > 0)
924 --ready_to_print;
925 q->lines_to_print = 0;
926 }
927 }
928 }
929 else
930 {
931 p->status = CLOSED;
932 p->lines_to_print = 0;
933 }
934
935 --ready_to_read;
936}
937
938/* Put a file on hold until we start a new page,
939 since we've hit a form feed.
940
941 If we aren't dealing with parallel files, we must change the
942 status of all columns in the column list. */
943
944void
945hold_file (p)
946 COLUMN *p;
947{
948 COLUMN *q;
949 int i;
950
951 if (!parallel_files)
952 for (q = column_vector, i = columns; i; ++q, --i)
953 q->status = ON_HOLD;
954 else
955 p->status = ON_HOLD;
956 p->lines_to_print = 0;
957 --ready_to_read;
958}
959
960/* Undo hold_file -- go through the column list and change any
961 ON_HOLD columns to OPEN. Used at the end of each page. */
962
963void
964reset_status ()
965{
966 int i = columns;
967 COLUMN *p;
968
969 for (p = column_vector; i; --i, ++p)
970 if (p->status == ON_HOLD)
971 {
972 p->status = OPEN;
973 ready_to_read++;
974 }
975}
976\f
977/* Print a single file, or multiple files in parallel.
978
979 Set up the list of columns, opening the necessary files.
980 Allocate space for storing columns, if necessary.
981 Skip to first_page, if user has asked to skip leading pages.
982 Determine which functions are appropriate to store/print lines
983 in each column.
984 Print the file(s). */
985
986void
987print_files (number_of_files, av)
988 int number_of_files;
989 char **av;
990{
991 init_parameters (number_of_files);
992 if (init_fps (number_of_files, av))
993 return;
994 if (storing_columns)
995 init_store_cols ();
996
997 if (first_page > 1)
998 {
999 if (!skip_to_page (first_page))
1000 return;
1001 else
1002 page_number = first_page;
1003 }
1004 else
1005 page_number = 1;
1006
1007 init_funcs ();
1008
1009 line_number = 1;
1010 while (print_page ())
1011 ;
1012}
1013\f
1014/* Generous estimate of number of characters taken up by "Jun 7 00:08 " and
1015 "Page NNNNN". */
1016#define CHARS_FOR_DATE_AND_PAGE 50
1017
1018/* Initialize header information.
1019 If DESC is non-negative, it is a file descriptor open to
1020 FILENAME for reading.
1021
1022 Allocate space for a header string,
1023 Determine the time, insert file name or user-specified string.
1024
1025 It might be nice to have a "blank headers" option, since
1026 pr -h "" still prints the date and page number. */
1027
1028void
1029init_header (filename, desc)
1030 char *filename;
1031 int desc;
1032{
1033 int chars_per_header;
1034 char *f = filename;
1035 char *t, *middle;
1036 struct stat st;
1037
1038 if (filename == 0)
1039 f = "";
1040
1041 /* If parallel files or standard input, use current time. */
1042 if (desc < 0 || !strcmp (filename, "-") || fstat (desc, &st))
1043 st.st_mtime = time ((time_t *) 0);
1044 t = ctime (&st.st_mtime);
1045
1046 t[16] = '\0'; /* Mark end of month and time string. */
1047 t[24] = '\0'; /* Mark end of year string. */
1048
1049 middle = standard_header ? f : custom_header;
1050
1051 chars_per_header = strlen (middle) + CHARS_FOR_DATE_AND_PAGE + 1;
1052 if (header != (char *) 0)
1053 free (header);
1054 header = (char *) malloc (chars_per_header * sizeof (char));
1055
1056 sprintf (header, "%s %s %s Page", &t[4], &t[20], middle);
1057}
1058\f
1059/* Set things up for printing a page
1060
1061 Scan through the columns ...
1062 Determine which are ready to print
1063 (i.e., which have lines stored or open files)
1064 Set p->lines_to_print appropriately
1065 (to p->lines_stored if we're storing, or lines_per_body
1066 if we're reading straight from the file)
1067 Keep track of this total so we know when to stop printing */
1068
1069void
1070init_page ()
1071{
1072 int j;
1073 COLUMN *p;
1074
1075 ready_to_print = 0;
1076
1077 if (storing_columns)
1078 {
1079 store_columns ();
1080 for (j = columns - 1, p = column_vector; j; --j, ++p)
1081 if ((p->lines_to_print = p->lines_stored) != 0)
1082 ++ready_to_print;
1083
1084 /* Last column. */
1085 if (balance_columns)
1086 {
1087 if ((p->lines_to_print = p->lines_stored) != 0)
1088 ++ready_to_print;
1089 }
1090 /* Since we're not balancing columns, we don't need to store
1091 the rightmost column. Read it straight from the file. */
1092 else
1093 {
1094 if (p->status == OPEN)
1095 {
1096 p->lines_to_print = lines_per_body;
1097 ++ready_to_print;
1098 }
1099 else
1100 p->lines_to_print = 0;
1101 }
1102 }
1103 else
1104 for (j = columns, p = column_vector; j; --j, ++p)
1105 if (p->status == OPEN)
1106 {
1107 p->lines_to_print = lines_per_body;
1108 ++ready_to_print;
1109 }
1110 else
1111 p->lines_to_print = 0;
1112}
1113
1114/* Print one page.
1115
1116 As long as there are lines left on the page and columns ready to print,
1117 Scan across the column list
1118 if the column has stored lines or the file is open
1119 pad to the appropriate spot
1120 print the column
1121 pad the remainder of the page with \n or \f as requested
1122 reset the status of all files -- any files which where on hold because
1123 of formfeeds are now put back into the lineup. */
1124
1125int
1126print_page ()
1127{
1128 int j;
1129 int lines_left;
1130 COLUMN *p;
1131
1132 /* Used as an accumulator (with | operator) of successive values of
1133 print_vertical_padding. The trick is to set print_vertical_padding
1134 to zero before each run through the inner loop, then after that
1135 loop, it tells us whether a line was actually printed (whether a
1136 newline needs to be output -- or two for double spacing). But those
1137 values have to be accumulated (in pvp) so we can invoke pad_down
1138 properly after the outer loop completes. */
1139 int pvp;
1140
1141 init_page ();
1142
1143 if (!ready_to_print)
1144 return FALSE;
1145
1146 if (extremities)
1147 print_a_header = TRUE;
1148
1149 /* Don't pad unless we know a page was printed. */
1150 print_vertical_padding = FALSE;
1151 pvp = FALSE;
1152
1153 lines_left = double_space ? 2 * lines_per_body : lines_per_body;
1154
1155 for (; lines_left > 0 && ready_to_print > 0; --lines_left)
1156 {
1157 output_position = 0;
1158 spaces_not_printed = 0;
1159 separators_not_printed = 0;
1160 print_vertical_padding = 0;
1161
1162 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1163 {
1164 input_position = 0;
1165 if (p->lines_to_print > 0)
1166 {
1167 padding_not_printed = p->start_position;
1168
1169 if (!(p->print_func) (p))
1170 read_rest_of_line (p);
1171 pvp |= print_vertical_padding;
1172
1173 if (use_column_separator)
1174 ++separators_not_printed;
1175
1176 if (--p->lines_to_print <= 0)
1177 if (--ready_to_print <= 0)
1178 break;
1179 }
1180 }
1181
1182 if (print_vertical_padding)
1183 putchar ('\n');
1184
1185 if (double_space && pvp && extremities)
1186 {
1187 putchar ('\n');
1188 --lines_left;
1189 }
1190 }
1191
1192 print_vertical_padding = pvp;
1193
1194 if (print_vertical_padding && extremities)
1195 pad_down (lines_left + lines_per_footer);
1196
1197 reset_status (); /* Change ON_HOLD to OPEN. */
1198
1199 return TRUE; /* More pages to go. */
1200}
1201\f
1202/* Allocate space for storing columns.
1203
1204 This is necessary when printing multiple columns from a single file.
1205 Lines are stored consecutively in buff, separated by '\0'.
1206 (We can't use a fixed offset since with the '-s' flag lines aren't
1207 truncated.)
1208
1209 We maintain a list (line_vector) of pointers to the beginnings
1210 of lines in buff. We allocate one more than the number of lines
1211 because the last entry tells us the index of the last character,
1212 which we need to know in order to print the last line in buff. */
1213
1214void
1215init_store_cols ()
1216{
1217 int total_lines = lines_per_body * columns;
1218 int chars_if_truncate = total_lines * (chars_per_column + 1);
1219
1220 if (line_vector != (int *) 0)
1221 free ((int *) line_vector);
1222 line_vector = (int *) malloc ((total_lines + 1) * sizeof (int *));
1223
1224 if (end_vector != (int *) 0)
1225 free ((int *) end_vector);
1226 end_vector = (int *) malloc (total_lines * sizeof (int *));
1227
1228 if (buff != (char *) 0)
1229 free (buff);
1230 chars_per_buff = use_column_separator ? 2 * chars_if_truncate
1231 : chars_if_truncate; /* Tune this. */
1232 buff = (char *) malloc (chars_per_buff * sizeof (char));
1233}
1234
1235/* Store all but the rightmost column.
1236 (Used when printing a single file in multiple downward columns)
1237
1238 For each column
1239 set p->current_line to be the index in line_vector of the
1240 first line in the column
1241 For each line in the column
1242 store the line in buff
1243 add to line_vector the index of the line's first char
1244 buff_start is the index in buff of the first character in the
1245 current line. */
1246
1247void
1248store_columns ()
1249{
1250 int i, j;
1251 int line = 0;
1252 int buff_start;
1253 int last_col; /* The rightmost column which will be saved in buff */
1254 COLUMN *p;
1255
1256 buff_current = 0;
1257 buff_start = 0;
1258
1259 if (balance_columns)
1260 last_col = columns;
1261 else
1262 last_col = columns - 1;
1263
1264 for (i = 1, p = column_vector; i <= last_col; ++i, ++p)
1265 p->lines_stored = 0;
1266
1267 for (i = 1, p = column_vector; i <= last_col && ready_to_read; ++i, ++p)
1268 {
1269 p->current_line = line;
1270 for (j = lines_per_body; j && ready_to_read; --j)
1271
1272 if (p->status == OPEN) /* Redundant. Clean up. */
1273 {
1274 input_position = 0;
1275
1276 if (!read_line (p, i))
1277 read_rest_of_line (p);
1278
1279 if (p->status == OPEN
1280 || buff_start != buff_current)
1281 {
1282 ++p->lines_stored;
1283 line_vector[line] = buff_start;
1284 end_vector[line++] = input_position;
1285 buff_start = buff_current;
1286 }
1287 }
1288 }
1289
1290 /* Keep track of the location of the last char in buff. */
1291 line_vector[line] = buff_start;
1292
1293 if (balance_columns && p->lines_stored != lines_per_body)
1294 balance (line);
1295}
1296
1297void
1298balance (total_stored)
1299 int total_stored;
1300{
1301 COLUMN *p;
1302 int i, lines;
1303 int first_line = 0;
1304
1305 for (i = 1, p = column_vector; i <= columns; ++i, ++p)
1306 {
1307 lines = total_stored / columns;
1308 if (i <= total_stored % columns)
1309 ++lines;
1310
1311 p->lines_stored = lines;
1312 p->current_line = first_line;
1313
1314 first_line += lines;
1315 }
1316}
1317
1318/* Store a character in the buffer. */
1319
1320void
1321store_char (c)
1322 int c;
1323{
1324 if (buff_current >= chars_per_buff)
1325 {
1326 /* May be too generous. */
1327 chars_per_buff = 2 * chars_per_buff;
1328 buff = (char *) realloc (buff, chars_per_buff * sizeof (char));
1329 }
1330 buff[buff_current++] = (char) c;
1331}
1332
1333void
1334number (p)
1335 COLUMN *p;
1336{
1337 int i;
1338 char *s;
1339
1340 sprintf (number_buff, "%*d", chars_per_number, line_number++);
1341 s = number_buff;
1342 for (i = chars_per_number; i > 0; i--)
1343 (p->char_func) ((int) *s++);
1344
1345 if (number_separator == input_tab_char)
1346 {
1347 i = number_width - chars_per_number;
1348 while (i-- > 0)
1349 (p->char_func) ((int) ' ');
1350 }
1351 else
1352 (p->char_func) ((int) number_separator);
1353
1354 if (truncate_lines && !parallel_files)
1355 input_position += number_width;
1356}
1357\f
1358/* Print (or store) padding until the current horizontal position
1359 is position. */
1360
1361void
1362pad_across_to (position)
1363 int position;
1364{
1365 register int h = output_position;
1366
1367 if (tabify_output)
1368 spaces_not_printed = position - output_position;
1369 else
1370 {
1371 while (++h <= position)
1372 putchar (' ');
1373 output_position = position;
1374 }
1375}
1376
1377/* Pad to the bottom of the page.
1378
1379 If the user has requested a formfeed, use one.
1380 Otherwise, use newlines. */
1381
1382void
1383pad_down (lines)
1384 int lines;
1385{
1386 register int i;
1387
1388 if (use_form_feed)
1389 putchar ('\f');
1390 else
1391 for (i = lines; i; --i)
1392 putchar ('\n');
1393}
1394
1395/* Read the rest of the line.
1396
1397 Read from the current column's file until an end of line is
1398 hit. Used when we've truncated a line and we no longer need
1399 to print or store its characters. */
1400
1401void
1402read_rest_of_line (p)
1403 COLUMN *p;
1404{
1405 register int c;
1406 FILE *f = p->fp;
1407
1408 while ((c = getc (f)) != '\n')
1409 {
1410 if (c == '\f')
1411 {
1412 hold_file (p);
1413 break;
1414 }
1415 else if (c == EOF)
1416 {
1417 close_file (p);
1418 break;
1419 }
1420 }
1421}
1422\f
1423/* If we're tabifying output,
1424
1425 When print_char encounters white space it keeps track
1426 of our desired horizontal position and delays printing
1427 until this function is called. */
1428
1429void
1430print_white_space ()
1431{
1432 register int h_new;
1433 register int h_old = output_position;
1434 register int goal = h_old + spaces_not_printed;
1435
1436 while (goal - h_old > 1
1437 && (h_new = pos_after_tab (chars_per_output_tab, h_old)) <= goal)
1438 {
1439 putchar (output_tab_char);
1440 h_old = h_new;
1441 }
1442 while (++h_old <= goal)
1443 putchar (' ');
1444
1445 output_position = goal;
1446 spaces_not_printed = 0;
1447}
1448
1449/* Print column separators.
1450
1451 We keep a count until we know that we'll be printing a line,
1452 then print_separators() is called. */
1453
1454void
1455print_separators ()
1456{
1457 for (; separators_not_printed > 0; --separators_not_printed)
1458 print_char (column_separator);
1459}
1460
1461/* Print (or store, depending on p->char_func) a clump of N
1462 characters. */
1463
1464void
1465print_clump (p, n, clump)
1466 COLUMN *p;
1467 int n;
1468 int *clump;
1469{
1470 while (n--)
1471 (p->char_func) (*clump++);
1472}
1473
1474/* Print a character.
1475
1476 If we're tabifying, all tabs have been converted to spaces by
1477 process_char(). Keep a count of consecutive spaces, and when
1478 a nonspace is encountered, call print_white_space() to print the
1479 required number of tabs and spaces. */
1480
1481void
1482print_char (c)
1483 int c;
1484{
1485 if (tabify_output)
1486 {
1487 if (c == ' ')
1488 {
1489 ++spaces_not_printed;
1490 return;
1491 }
1492 else if (spaces_not_printed > 0)
1493 print_white_space ();
1494
1495 /* Nonprintables are assumed to have width 0, except '\b'. */
1496 if (!ISPRINT (c))
1497 {
1498 if (c == '\b')
1499 --output_position;
1500 }
1501 else
1502 ++output_position;
1503 }
1504 putchar (c);
1505}
1506
1507/* Skip to page PAGE before printing. */
1508
1509int
1510skip_to_page (page)
1511 int page;
1512{
1513 int n, i, j;
1514 COLUMN *p;
1515
1516 for (n = 1; n < page; ++n)
1517 {
1518 for (i = 1; i <= lines_per_body; ++i)
1519 {
1520 for (j = 1, p = column_vector; j <= columns; ++j, ++p)
1521 read_rest_of_line (p);
1522 }
1523 reset_status ();
1524 }
1525 return ready_to_read > 0;
1526}
1527
1528/* Print a header.
1529
1530 Formfeeds are assumed to use up two lines at the beginning of
1531 the page. */
1532
1533void
1534print_header ()
1535{
1536 if (!use_form_feed)
1537 fprintf (stdout, "\n\n");
1538
1539 output_position = 0;
1540 pad_across_to (chars_per_margin);
1541 print_white_space ();
1542
1543 fprintf (stdout, "%s %d\n\n\n", header, page_number++);
1544
1545 print_a_header = FALSE;
1546 output_position = 0;
1547}
1548
1549/* Print (or store, if p->char_func is store_char()) a line.
1550
1551 Read a character to determine whether we have a line or not.
1552 (We may hit EOF, \n, or \f)
1553
1554 Once we know we have a line,
1555 set print_vertical_padding = TRUE, meaning it's safe
1556 to pad down at the end of the page, since we do have a page.
1557 print a header if needed.
1558 pad across to padding_not_printed if needed.
1559 print any separators which need to be printed.
1560 print a line number if it needs to be printed.
1561
1562 Print the clump which corresponds to the first character.
1563
1564 Enter a loop and keep printing until an end of line condition
1565 exists, or until we exceed chars_per_column.
1566
1567 Return FALSE if we exceed chars_per_column before reading
1568 an end of line character, TRUE otherwise. */
1569
1570int
1571read_line (p)
1572 COLUMN *p;
1573{
1574 register int c, chars;
1575 int last_input_position;
1576
1577 c = getc (p->fp);
1578
1579 last_input_position = input_position;
1580 switch (c)
1581 {
1582 case '\f':
1583 hold_file (p);
1584 return TRUE;
1585 case EOF:
1586 close_file (p);
1587 return TRUE;
1588 case '\n':
1589 break;
1590 default:
1591 chars = char_to_clump (c);
1592 }
1593
1594 if (truncate_lines && input_position > chars_per_column)
1595 {
1596 input_position = last_input_position;
1597 return FALSE;
1598 }
1599
1600 if (p->char_func != store_char)
1601 {
1602 print_vertical_padding = TRUE;
1603
1604 if (print_a_header)
1605 print_header ();
1606
1607 if (padding_not_printed != ANYWHERE)
1608 {
1609 pad_across_to (padding_not_printed);
1610 padding_not_printed = ANYWHERE;
1611 }
1612
1613 if (use_column_separator)
1614 print_separators ();
1615 }
1616
1617 if (p->numbered)
1618 number (p);
1619
1620 if (c == '\n')
1621 return TRUE;
1622
1623 print_clump (p, chars, clump_buff);
1624
1625 for (;;)
1626 {
1627 c = getc (p->fp);
1628
1629 switch (c)
1630 {
1631 case '\n':
1632 return TRUE;
1633 case '\f':
1634 hold_file (p);
1635 return TRUE;
1636 case EOF:
1637 close_file (p);
1638 return TRUE;
1639 }
1640
1641 last_input_position = input_position;
1642 chars = char_to_clump (c);
1643 if (truncate_lines && input_position > chars_per_column)
1644 {
1645 input_position = last_input_position;
1646 return FALSE;
1647 }
1648
1649 print_clump (p, chars, clump_buff);
1650 }
1651}
1652
1653/* Print a line from buff.
1654
1655 If this function has been called, we know we have something to
1656 print. Therefore we set print_vertical_padding to TRUE, print
1657 a header if necessary, pad across if necessary, and print
1658 separators if necessary.
1659
1660 Return TRUE, meaning there is no need to call read_rest_of_line. */
1661
1662int
1663print_stored (p)
1664 COLUMN *p;
1665{
1666 int line = p->current_line++;
1667 register char *first = &buff[line_vector[line]];
1668 register char *last = &buff[line_vector[line + 1]];
1669
1670 print_vertical_padding = TRUE;
1671
1672 if (print_a_header)
1673 print_header ();
1674
1675 if (padding_not_printed != ANYWHERE)
1676 {
1677 pad_across_to (padding_not_printed);
1678 padding_not_printed = ANYWHERE;
1679 }
1680
1681 if (use_column_separator)
1682 print_separators ();
1683
1684 while (first != last)
1685 print_char (*first++);
1686
1687 if (spaces_not_printed == 0)
1688 output_position = p->start_position + end_vector[line];
1689
1690 return TRUE;
1691}
1692
1693/* Convert a character to the proper format and return the number of
1694 characters in the resulting clump. Increment input_position by
1695 the width of the clump.
1696
1697 Tabs are converted to clumps of spaces.
1698 Nonprintable characters may be converted to clumps of escape
1699 sequences or control prefixes.
1700
1701 Note: the width of a clump is not necessarily equal to the number of
1702 characters in clump_buff. (e.g, the width of '\b' is -1, while the
1703 number of characters is 1.) */
1704
1705int
1706char_to_clump (c)
1707 int c;
1708{
1709 register int *s = clump_buff;
1710 register int i;
1711 char esc_buff[4];
1712 int width;
1713 int chars;
1714
1715 if (c == input_tab_char)
1716 {
1717 width = tab_width (chars_per_input_tab, input_position);
1718
1719 if (untabify_input)
1720 {
1721 for (i = width; i; --i)
1722 *s++ = ' ';
1723 chars = width;
1724 }
1725 else
1726 {
1727 *s = c;
1728 chars = 1;
1729 }
1730
1731 }
1732 else if (!ISPRINT (c))
1733 {
1734 if (use_esc_sequence)
1735 {
1736 width = 4;
1737 chars = 4;
1738 *s++ = '\\';
1739 sprintf (esc_buff, "%03o", c);
1740 for (i = 0; i <= 2; ++i)
1741 *s++ = (int) esc_buff[i];
1742 }
1743 else if (use_cntrl_prefix)
1744 {
1745 if (c < 0200)
1746 {
1747 width = 2;
1748 chars = 2;
1749 *s++ = '^';
1750 *s++ = c ^ 0100;
1751 }
1752 else
1753 {
1754 width = 4;
1755 chars = 4;
1756 *s++ = '\\';
1757 sprintf (esc_buff, "%03o", c);
1758 for (i = 0; i <= 2; ++i)
1759 *s++ = (int) esc_buff[i];
1760 }
1761 }
1762 else if (c == '\b')
1763 {
1764 width = -1;
1765 chars = 1;
1766 *s = c;
1767 }
1768 else
1769 {
1770 width = 0;
1771 chars = 1;
1772 *s = c;
1773 }
1774 }
1775 else
1776 {
1777 width = 1;
1778 chars = 1;
1779 *s = c;
1780 }
1781
1782 input_position += width;
1783 return chars;
1784}
1785
1786/* We've just printed some files and need to clean up things before
1787 looking for more options and printing the next batch of files.
1788
1789 Free everything we've malloc'ed, except `header'. */
1790
1791void
1792cleanup ()
1793{
1794 if (number_buff)
1795 free (number_buff);
1796 if (clump_buff)
1797 free (clump_buff);
1798 if (column_vector)
1799 free (column_vector);
1800 if (line_vector)
1801 free (line_vector);
1802 if (end_vector)
1803 free (end_vector);
1804 if (buff)
1805 free (buff);
1806}
1807\f
1808/* Complain, print a usage message, and die. */
1809
1810void
1811usage (reason)
1812 char *reason;
1813{
1814 if (reason)
1815 fprintf (stderr, "%s: %s\n", program_name, reason);
1816
1817 fprintf (stderr, "\
1818Usage: %s [+PAGE] [-COLUMN] [-abcdfFmrtv] [-e[in-tab-char[in-tab-width]]]\n\
1819 [-h header] [-i[out-tab-char[out-tab-width]]] [-l page-length]\n\
1820 [-n[number-separator[digits]]] [-o left-margin]\n\
1821 [-s[column-separator]] [-w page-width] [file...]\n",
1822 program_name);
1823 exit (2);
1824}
1825
1826/* error.c -- error handler for noninteractive utilities
1827 Copyright (C) 1990, 1991 Free Software Foundation, Inc.
1828
1829 This program is free software; you can redistribute it and/or modify
1830 it under the terms of the GNU General Public License as published by
1831 the Free Software Foundation; either version 2, or (at your option)
1832 any later version.
1833
1834 This program is distributed in the hope that it will be useful,
1835 but WITHOUT ANY WARRANTY; without even the implied warranty of
1836 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1837 GNU General Public License for more details.
1838
1839 You should have received a copy of the GNU General Public License
1840 along with this program; if not, write to the Free Software
1841 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
1842
1843/* David MacKenzie */
1844
1845
1846#include <stdarg.h>
1847#define VA_START(args, lastarg) va_start(args, lastarg)
1848
1849/* Print the program name and error message MESSAGE, which is a printf-style
1850 format string with optional args.
1851 If ERRNUM is nonzero, print its corresponding system error message.
1852 Exit with status STATUS if it is nonzero. */
1853/* VARARGS */
1854void
1855error (int status, int errnum, char *message, ...)
1856{
1857 extern char *program_name;
1858 va_list args;
1859
1860 fprintf (stderr, "%s: ", program_name);
1861 va_start (args, message);
1862 vfprintf (stderr, message, args);
1863 va_end (args);
1864 if (errnum)
1865 fprintf (stderr, ": %s", strerror (errnum));
1866 putc ('\n', stderr);
1867 fflush (stderr);
1868 if (status)
1869 exit (status);
1870}