1 /* csplit - split a file into sections determined by context lines
2 Copyright (C) 91, 1995-2004 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Written by Stuart Kemp, cpsrk@groper.jcu.edu.au.
19 Modified by David MacKenzie, djm@gnu.ai.mit.edu. */
25 #include <sys/types.h>
34 #include "safe-read.h"
39 # define sigprocmask(How, Set, Oset) /* empty */
43 /* The official name of this program (e.g., no `g' prefix). */
44 #define PROGRAM_NAME "csplit"
46 #define AUTHORS "Stuart Kemp", "David MacKenzie"
48 /* Increment size of area for control records. */
51 /* The default prefix for output file names. */
52 #define DEFAULT_PREFIX "xx"
54 /* A compiled pattern arg. */
57 char *regexpr; /* Non-compiled regular expression. */
58 struct re_pattern_buffer re_compiled; /* Compiled regular expression. */
59 intmax_t offset; /* Offset from regexp to split at. */
60 uintmax_t lines_required; /* Number of lines required. */
61 uintmax_t repeat; /* Repeat count. */
62 int argnum; /* ARGV index. */
63 bool repeat_forever; /* True if `*' used as a repeat count. */
64 bool ignore; /* If true, produce no output (for regexp). */
67 /* Initial size of data area in buffers. */
68 #define START_SIZE 8191
70 /* Increment size for data area. */
71 #define INCR_SIZE 2048
73 /* Number of lines kept in each node in line list. */
77 /* Some small values to test the algorithms. */
78 # define START_SIZE 200
83 /* A string with a length count. */
90 /* Pointers to the beginnings of lines in the buffer area.
91 These structures are linked together if needed. */
94 unsigned int used; /* Number of offsets used in this struct. */
95 unsigned int insert_index; /* Next offset to use when inserting line. */
96 unsigned int retrieve_index; /* Next index to use when retrieving line. */
97 struct cstring starts[CTRL_SIZE]; /* Lines in the data area. */
98 struct line *next; /* Next in linked list. */
101 /* The structure to hold the input lines.
102 Contains a pointer to the data area and a list containing
103 pointers to the individual lines. */
106 size_t bytes_alloc; /* Size of the buffer area. */
107 size_t bytes_used; /* Bytes used in the buffer area. */
108 uintmax_t start_line; /* First line number in this buffer. */
109 uintmax_t first_available; /* First line that can be retrieved. */
110 size_t num_lines; /* Number of complete lines in this buffer. */
111 char *buffer; /* Data area. */
112 struct line *line_start; /* Head of list of pointers to lines. */
113 struct line *curr_line; /* The line start record currently in use. */
114 struct buffer_record *next;
117 static void close_output_file (void);
118 static void create_output_file (void);
119 static void delete_all_files (void);
120 static void save_line_to_file (const struct cstring *line);
121 void usage (int status);
123 /* The name this program was run with. */
126 /* Input file descriptor. */
127 static int input_desc = 0;
129 /* Start of buffer list. */
130 static struct buffer_record *head = NULL;
132 /* Partially read line. */
133 static char *hold_area = NULL;
135 /* Number of bytes in `hold_area'. */
136 static size_t hold_count = 0;
138 /* Number of the last line in the buffers. */
139 static uintmax_t last_line_number = 0;
141 /* Number of the line currently being examined. */
142 static uintmax_t current_line = 0;
144 /* If true, we have read EOF. */
145 static bool have_read_eof = false;
147 /* Name of output files. */
148 static char * volatile filename_space = NULL;
150 /* Prefix part of output file names. */
151 static char * volatile prefix = NULL;
153 /* Suffix part of output file names. */
154 static char * volatile suffix = NULL;
156 /* Number of digits to use in output file names. */
157 static int volatile digits = 2;
159 /* Number of files created so far. */
160 static unsigned int volatile files_created = 0;
162 /* Number of bytes written to current file. */
163 static uintmax_t bytes_written;
165 /* Output file pointer. */
166 static FILE *output_stream = NULL;
168 /* Output file name. */
169 static char *output_filename = NULL;
171 /* Perhaps it would be cleaner to pass arg values instead of indexes. */
172 static char **global_argv;
174 /* If true, do not print the count of bytes in each output file. */
175 static bool suppress_count;
177 /* If true, remove output files on error. */
178 static bool volatile remove_files;
180 /* If true, remove all output files which have a zero length. */
181 static bool elide_empty_files;
183 /* The compiled pattern arguments, which determine how to split
185 static struct control *controls;
187 /* Number of elements in `controls'. */
188 static size_t control_used;
190 /* The set of signals that are caught. */
191 static sigset_t caught_signals;
193 static struct option const longopts[] =
195 {"digits", required_argument, NULL, 'n'},
196 {"quiet", no_argument, NULL, 'q'},
197 {"silent", no_argument, NULL, 's'},
198 {"keep-files", no_argument, NULL, 'k'},
199 {"elide-empty-files", no_argument, NULL, 'z'},
200 {"prefix", required_argument, NULL, 'f'},
201 {"suffix-format", required_argument, NULL, 'b'},
202 {GETOPT_HELP_OPTION_DECL},
203 {GETOPT_VERSION_OPTION_DECL},
207 /* Optionally remove files created so far; then exit.
208 Called when an error detected. */
215 close_output_file ();
217 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
219 sigprocmask (SIG_SETMASK, &oldset, NULL);
222 static void cleanup_fatal (void) ATTRIBUTE_NORETURN;
231 interrupt_handler (int sig)
234 signal (sig, SIG_IGN);
239 signal (sig, SIG_DFL);
243 /* Keep track of NUM bytes of a partial line in buffer START.
244 These bytes will be retrieved later when another large buffer is read.
245 It is not necessary to create a new buffer for these bytes; instead,
246 we keep a pointer to the existing buffer. This buffer *is* on the
247 free list, and when the next buffer is obtained from this list
248 (even if it is this one), these bytes will be placed at the
249 start of the new buffer. */
252 save_to_hold_area (char *start, size_t num)
258 /* Read up to MAX_N_BYTES bytes from the input stream into DEST.
259 Return the number of bytes read. */
262 read_input (char *dest, size_t max_n_bytes)
266 if (max_n_bytes == 0)
269 bytes_read = safe_read (input_desc, dest, max_n_bytes);
272 have_read_eof = true;
274 if (bytes_read == SAFE_READ_ERROR)
276 error (0, errno, _("read error"));
283 /* Initialize existing line record P. */
286 clear_line_control (struct line *p)
290 p->retrieve_index = 0;
293 /* Return a new, initialized line record. */
296 new_line_control (void)
298 struct line *p = xmalloc (sizeof *p);
301 clear_line_control (p);
306 /* Record LINE_START, which is the address of the start of a line
307 of length LINE_LEN in the large buffer, in the lines buffer of B. */
310 keep_new_line (struct buffer_record *b, char *line_start, size_t line_len)
314 /* If there is no existing area to keep line info, get some. */
315 if (b->line_start == NULL)
316 b->line_start = b->curr_line = new_line_control ();
318 /* If existing area for lines is full, get more. */
319 if (b->curr_line->used == CTRL_SIZE)
321 b->curr_line->next = new_line_control ();
322 b->curr_line = b->curr_line->next;
327 /* Record the start of the line, and update counters. */
328 l->starts[l->insert_index].str = line_start;
329 l->starts[l->insert_index].len = line_len;
334 /* Scan the buffer in B for newline characters
335 and record the line start locations and lengths in B.
336 Return the number of lines found in this buffer.
338 There may be an incomplete line at the end of the buffer;
339 a pointer is kept to this area, which will be used when
340 the next buffer is filled. */
343 record_line_starts (struct buffer_record *b)
345 char *line_start; /* Start of current line. */
346 char *line_end; /* End of each line found. */
347 size_t bytes_left; /* Length of incomplete last line. */
348 size_t lines; /* Number of lines found. */
349 size_t line_length; /* Length of each line found. */
351 if (b->bytes_used == 0)
355 line_start = b->buffer;
356 bytes_left = b->bytes_used;
360 line_end = memchr (line_start, '\n', bytes_left);
361 if (line_end == NULL)
363 line_length = line_end - line_start + 1;
364 keep_new_line (b, line_start, line_length);
365 bytes_left -= line_length;
366 line_start = line_end + 1;
370 /* Check for an incomplete last line. */
375 keep_new_line (b, line_start, bytes_left);
379 save_to_hold_area (line_start, bytes_left);
382 b->num_lines = lines;
383 b->first_available = b->start_line = last_line_number + 1;
384 last_line_number += lines;
389 /* Return a new buffer with room to store SIZE bytes, plus
390 an extra byte for safety. */
392 static struct buffer_record *
393 create_new_buffer (size_t size)
395 struct buffer_record *new_buffer = xmalloc (sizeof *new_buffer);
397 new_buffer->buffer = xmalloc (size + 1);
399 new_buffer->bytes_alloc = size;
400 new_buffer->line_start = new_buffer->curr_line = NULL;
405 /* Return a new buffer of at least MINSIZE bytes. If a buffer of at
406 least that size is currently free, use it, otherwise create a new one. */
408 static struct buffer_record *
409 get_new_buffer (size_t min_size)
411 struct buffer_record *new_buffer; /* Buffer to return. */
412 size_t alloc_size; /* Actual size that will be requested. */
414 alloc_size = START_SIZE;
415 if (alloc_size < min_size)
417 size_t s = min_size - alloc_size + INCR_SIZE - 1;
418 alloc_size += s - s % INCR_SIZE;
421 new_buffer = create_new_buffer (alloc_size);
423 new_buffer->num_lines = 0;
424 new_buffer->bytes_used = 0;
425 new_buffer->start_line = new_buffer->first_available = last_line_number + 1;
426 new_buffer->next = NULL;
432 free_buffer (struct buffer_record *buf)
437 /* Append buffer BUF to the linked list of buffers that contain
438 some data yet to be processed. */
441 save_buffer (struct buffer_record *buf)
443 struct buffer_record *p;
446 buf->curr_line = buf->line_start;
452 for (p = head; p->next; p = p->next)
458 /* Fill a buffer of input.
460 Set the initial size of the buffer to a default.
461 Fill the buffer (from the hold area and input stream)
462 and find the individual lines.
463 If no lines are found (the buffer is too small to hold the next line),
464 release the current buffer (whose contents would have been put in the
465 hold area) and repeat the process with another large buffer until at least
466 one entire line has been read.
468 Return true if a new buffer was obtained, otherwise false
469 (in which case end-of-file must have been encountered). */
474 struct buffer_record *b;
475 size_t bytes_wanted = START_SIZE; /* Minimum buffer size. */
476 size_t bytes_avail; /* Size of new buffer created. */
477 size_t lines_found; /* Number of lines in this new buffer. */
478 char *p; /* Place to load into buffer. */
483 /* We must make the buffer at least as large as the amount of data
484 in the partial line left over from the last call. */
485 if (bytes_wanted < hold_count)
486 bytes_wanted = hold_count;
490 b = get_new_buffer (bytes_wanted);
491 bytes_avail = b->bytes_alloc; /* Size of buffer returned. */
494 /* First check the `holding' area for a partial line. */
498 memcpy (p, hold_area, hold_count);
500 b->bytes_used += hold_count;
501 bytes_avail -= hold_count;
505 b->bytes_used += read_input (p, bytes_avail);
507 lines_found = record_line_starts (b);
508 bytes_wanted = b->bytes_alloc * 2;
512 while (!lines_found && !have_read_eof);
517 return lines_found != 0;
520 /* Return the line number of the first line that has not yet been retrieved. */
523 get_first_line_in_buffer (void)
525 if (head == NULL && !load_buffer ())
526 error (EXIT_FAILURE, errno, _("input disappeared"));
528 return head->first_available;
531 /* Return a pointer to the logical first line in the buffer and make the
532 next line the logical first line.
533 Return NULL if there is no more input. */
535 static struct cstring *
538 /* If non-NULL, this is the buffer for which the previous call
539 returned the final line. So now, presuming that line has been
540 processed, we can free the buffer and reset this pointer. */
541 static struct buffer_record *prev_buf = NULL;
543 struct cstring *line; /* Return value. */
544 struct line *l; /* For convenience. */
548 free_buffer (prev_buf);
552 if (head == NULL && !load_buffer ())
555 if (current_line < head->first_available)
556 current_line = head->first_available;
558 ++(head->first_available);
562 line = &l->starts[l->retrieve_index];
564 /* Advance index to next line. */
565 if (++l->retrieve_index == l->used)
567 /* Go on to the next line record. */
568 head->curr_line = l->next;
569 if (head->curr_line == NULL || head->curr_line->used == 0)
571 /* Go on to the next data block.
572 but first record the current one so we can free it
573 once the line we're returning has been processed. */
582 /* Search the buffers for line LINENUM, reading more input if necessary.
583 Return a pointer to the line, or NULL if it is not found in the file. */
585 static struct cstring *
586 find_line (uintmax_t linenum)
588 struct buffer_record *b;
590 if (head == NULL && !load_buffer ())
593 if (linenum < head->start_line)
598 if (linenum < b->start_line + b->num_lines)
600 /* The line is in this buffer. */
602 size_t offset; /* How far into the buffer the line is. */
605 offset = linenum - b->start_line;
606 /* Find the control record. */
607 while (offset >= CTRL_SIZE)
612 return &l->starts[offset];
614 if (b->next == NULL && !load_buffer ())
616 b = b->next; /* Try the next data block. */
620 /* Return true if at least one more line is available for input. */
625 return find_line (current_line + 1) == NULL;
628 /* Set the name of the input file to NAME and open it. */
631 set_input_file (const char *name)
633 if (STREQ (name, "-"))
637 input_desc = open (name, O_RDONLY);
639 error (EXIT_FAILURE, errno, "%s", name);
643 /* Write all lines from the beginning of the buffer up to, but
644 not including, line LAST_LINE, to the current output file.
645 If IGNORE is true, do not output lines selected here.
646 ARGNUM is the index in ARGV of the current pattern. */
649 write_to_file (uintmax_t last_line, bool ignore, int argnum)
651 struct cstring *line;
652 uintmax_t first_line; /* First available input line. */
653 uintmax_t lines; /* Number of lines to output. */
656 first_line = get_first_line_in_buffer ();
658 if (first_line > last_line)
660 error (0, 0, _("%s: line number out of range"), global_argv[argnum]);
664 lines = last_line - first_line;
666 for (i = 0; i < lines; i++)
668 line = remove_line ();
671 error (0, 0, _("%s: line number out of range"), global_argv[argnum]);
675 save_line_to_file (line);
679 /* Output any lines left after all regexps have been processed. */
682 dump_rest_of_file (void)
684 struct cstring *line;
686 while ((line = remove_line ()) != NULL)
687 save_line_to_file (line);
690 /* Handle an attempt to read beyond EOF under the control of record P,
691 on iteration REPETITION if nonzero. */
693 static void handle_line_error (const struct control *, uintmax_t)
696 handle_line_error (const struct control *p, uintmax_t repetition)
698 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
700 fprintf (stderr, _("%s: `%s': line number out of range"),
701 program_name, umaxtostr (p->lines_required, buf));
703 fprintf (stderr, _(" on repetition %s\n"), umaxtostr (repetition, buf));
705 fprintf (stderr, "\n");
710 /* Determine the line number that marks the end of this file,
711 then get those lines and save them to the output file.
712 P is the control record.
713 REPETITION is the repetition number. */
716 process_line_count (const struct control *p, uintmax_t repetition)
719 uintmax_t last_line_to_save = p->lines_required * (repetition + 1);
720 struct cstring *line;
722 create_output_file ();
724 linenum = get_first_line_in_buffer ();
726 while (linenum++ < last_line_to_save)
728 line = remove_line ();
730 handle_line_error (p, repetition);
731 save_line_to_file (line);
734 close_output_file ();
736 /* Ensure that the line number specified is not 1 greater than
737 the number of lines in the file. */
738 if (no_more_lines ())
739 handle_line_error (p, repetition);
742 static void regexp_error (struct control *, uintmax_t, bool) ATTRIBUTE_NORETURN;
744 regexp_error (struct control *p, uintmax_t repetition, bool ignore)
746 fprintf (stderr, _("%s: `%s': match not found"),
747 program_name, global_argv[p->argnum]);
751 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
752 fprintf (stderr, _(" on repetition %s\n"), umaxtostr (repetition, buf));
755 fprintf (stderr, "\n");
759 dump_rest_of_file ();
760 close_output_file ();
765 /* Read the input until a line matches the regexp in P, outputting
766 it unless P->IGNORE is true.
767 REPETITION is this repeat-count; 0 means the first time. */
770 process_regexp (struct control *p, uintmax_t repetition)
772 struct cstring *line; /* From input file. */
773 size_t line_len; /* To make "$" in regexps work. */
774 uintmax_t break_line; /* First line number of next file. */
775 bool ignore = p->ignore; /* If true, skip this section. */
779 create_output_file ();
781 /* If there is no offset for the regular expression, or
782 it is positive, then it is not necessary to buffer the lines. */
788 line = find_line (++current_line);
791 if (p->repeat_forever)
795 dump_rest_of_file ();
796 close_output_file ();
801 regexp_error (p, repetition, ignore);
803 line_len = line->len;
804 if (line->str[line_len - 1] == '\n')
806 ret = re_search (&p->re_compiled, line->str, line_len,
810 error (0, 0, _("error in regular expression search"));
815 line = remove_line ();
817 save_line_to_file (line);
825 /* Buffer the lines. */
828 line = find_line (++current_line);
831 if (p->repeat_forever)
835 dump_rest_of_file ();
836 close_output_file ();
841 regexp_error (p, repetition, ignore);
843 line_len = line->len;
844 if (line->str[line_len - 1] == '\n')
846 ret = re_search (&p->re_compiled, line->str, line_len,
850 error (0, 0, _("error in regular expression search"));
858 /* Account for any offset from this regexp. */
859 break_line = current_line + p->offset;
861 write_to_file (break_line, ignore, p->argnum);
864 close_output_file ();
867 current_line = break_line;
870 /* Split the input file according to the control records we have built. */
877 for (i = 0; i < control_used; i++)
880 if (controls[i].regexpr)
882 for (j = 0; (controls[i].repeat_forever
883 || j <= controls[i].repeat); j++)
884 process_regexp (&controls[i], j);
888 for (j = 0; (controls[i].repeat_forever
889 || j <= controls[i].repeat); j++)
890 process_line_count (&controls[i], j);
894 create_output_file ();
895 dump_rest_of_file ();
896 close_output_file ();
899 /* Return the name of output file number NUM. */
902 make_filename (unsigned int num)
904 strcpy (filename_space, prefix);
906 sprintf (filename_space+strlen(prefix), suffix, num);
908 sprintf (filename_space+strlen(prefix), "%0*u", digits, num);
909 return filename_space;
912 /* Create the next output file. */
915 create_output_file (void)
921 output_filename = make_filename (files_created);
923 /* Create the output file in a critical section, to avoid races. */
924 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
925 output_stream = fopen (output_filename, "w");
926 fopen_ok = (output_stream != NULL);
928 files_created += fopen_ok;
929 sigprocmask (SIG_SETMASK, &oldset, NULL);
933 error (0, fopen_errno, "%s", output_filename);
939 /* If requested, delete all the files we have created. This function
940 must be called only from critical sections. */
943 delete_all_files (void)
950 for (i = 0; i < files_created; i++)
952 const char *name = make_filename (i);
954 error (0, errno, "%s", name);
960 /* Close the current output file and print the count
961 of characters in this file. */
964 close_output_file (void)
968 if (ferror (output_stream))
970 error (0, 0, _("write error for `%s'"), output_filename);
971 output_stream = NULL;
974 if (fclose (output_stream) != 0)
976 error (0, errno, "%s", output_filename);
977 output_stream = NULL;
980 if (bytes_written == 0 && elide_empty_files)
986 /* Remove the output file in a critical section, to avoid races. */
987 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
988 unlink_ok = (unlink (output_filename) == 0);
989 unlink_errno = errno;
990 files_created -= unlink_ok;
991 sigprocmask (SIG_SETMASK, &oldset, NULL);
994 error (0, unlink_errno, "%s", output_filename);
1000 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
1001 fprintf (stdout, "%s\n", umaxtostr (bytes_written, buf));
1004 output_stream = NULL;
1008 /* Save line LINE to the output file and
1009 increment the character count for the current file. */
1012 save_line_to_file (const struct cstring *line)
1014 fwrite (line->str, sizeof (char), line->len, output_stream);
1015 bytes_written += line->len;
1018 /* Return a new, initialized control record. */
1020 static struct control *
1021 new_control_record (void)
1023 static size_t control_allocated = 0; /* Total space allocated. */
1026 if (control_used == control_allocated)
1027 controls = x2nrealloc (controls, &control_allocated, sizeof *controls);
1028 p = &controls[control_used++];
1031 p->repeat_forever = false;
1032 p->lines_required = 0;
1037 /* Check if there is a numeric offset after a regular expression.
1038 STR is the entire command line argument.
1039 P is the control record for this regular expression.
1040 NUM is the numeric part of STR. */
1043 check_for_offset (struct control *p, const char *str, const char *num)
1045 if (xstrtoimax (num, NULL, 10, &p->offset, "") != LONGINT_OK)
1046 error (EXIT_FAILURE, 0, _("%s: integer expected after delimiter"), str);
1049 /* Given that the first character of command line arg STR is '{',
1050 make sure that the rest of the string is a valid repeat count
1051 and store its value in P.
1052 ARGNUM is the ARGV index of STR. */
1055 parse_repeat_count (int argnum, struct control *p, char *str)
1060 end = str + strlen (str) - 1;
1062 error (EXIT_FAILURE, 0, _("%s: `}' is required in repeat count"), str);
1065 if (str+1 == end-1 && *(str+1) == '*')
1066 p->repeat_forever = true;
1069 if (xstrtoumax (str + 1, NULL, 10, &val, "") != LONGINT_OK)
1071 error (EXIT_FAILURE, 0,
1072 _("%s}: integer required between `{' and `}'"),
1073 global_argv[argnum]);
1081 /* Extract the regular expression from STR and check for a numeric offset.
1082 STR should start with the regexp delimiter character.
1083 Return a new control record for the regular expression.
1084 ARGNUM is the ARGV index of STR.
1085 Unless IGNORE is true, mark these lines for output. */
1087 static struct control *
1088 extract_regexp (int argnum, bool ignore, char *str)
1090 size_t len; /* Number of bytes in this regexp. */
1092 char *closing_delim;
1096 closing_delim = strrchr (str + 1, delim);
1097 if (closing_delim == NULL)
1098 error (EXIT_FAILURE, 0,
1099 _("%s: closing delimiter `%c' missing"), str, delim);
1101 len = closing_delim - str - 1;
1102 p = new_control_record ();
1106 p->regexpr = xmalloc (len + 1);
1107 strncpy (p->regexpr, str + 1, len);
1108 p->re_compiled.allocated = len * 2;
1109 p->re_compiled.buffer = xmalloc (p->re_compiled.allocated);
1110 p->re_compiled.fastmap = xmalloc (1 << CHAR_BIT);
1111 p->re_compiled.translate = 0;
1112 err = re_compile_pattern (p->regexpr, len, &p->re_compiled);
1115 error (0, 0, _("%s: invalid regular expression: %s"), str, err);
1119 if (closing_delim[1])
1120 check_for_offset (p, str, closing_delim + 1);
1125 /* Extract the break patterns from args START through ARGC - 1 of ARGV.
1126 After each pattern, check if the next argument is a repeat count. */
1129 parse_patterns (int argc, int start, char **argv)
1131 int i; /* Index into ARGV. */
1132 struct control *p; /* New control record created. */
1134 static uintmax_t last_val = 0;
1136 for (i = start; i < argc; i++)
1138 if (*argv[i] == '/' || *argv[i] == '%')
1140 p = extract_regexp (i, *argv[i] == '%', argv[i]);
1144 p = new_control_record ();
1147 if (xstrtoumax (argv[i], NULL, 10, &val, "") != LONGINT_OK)
1148 error (EXIT_FAILURE, 0, _("%s: invalid pattern"), argv[i]);
1150 error (EXIT_FAILURE, 0,
1151 _("%s: line number must be greater than zero"),
1155 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
1156 error (EXIT_FAILURE, 0,
1157 _("line number `%s' is smaller than preceding line number, %s"),
1158 argv[i], umaxtostr (last_val, buf));
1161 if (val == last_val)
1163 _("warning: line number `%s' is the same as preceding line number"),
1168 p->lines_required = val;
1171 if (i + 1 < argc && *argv[i + 1] == '{')
1173 /* We have a repeat count. */
1175 parse_repeat_count (i, p, argv[i]);
1181 get_format_flags (char **format_ptr)
1183 unsigned int count = 0;
1185 for (; **format_ptr; (*format_ptr)++)
1187 switch (**format_ptr)
1198 count |= 2; /* Allow for 0x prefix preceding an `x' conversion. */
1209 get_format_width (char **format_ptr)
1211 unsigned long int val = 0;
1213 if (ISDIGIT (**format_ptr)
1214 && (xstrtoul (*format_ptr, format_ptr, 10, &val, NULL) != LONGINT_OK
1216 error (EXIT_FAILURE, 0, _("invalid format width"));
1218 /* Allow for enough octal digits to represent the value of UINT_MAX,
1219 even if the field width is less than that. */
1220 return MAX (val, (sizeof (unsigned int) * CHAR_BIT + 2) / 3);
1224 get_format_prec (char **format_ptr)
1226 if (**format_ptr != '.')
1230 if (! ISDIGIT (**format_ptr))
1234 unsigned long int val;
1235 if (xstrtoul (*format_ptr, format_ptr, 10, &val, NULL) != LONGINT_OK
1237 error (EXIT_FAILURE, 0, _("invalid format precision"));
1243 get_format_conv_type (char **format_ptr)
1245 unsigned char ch = *(*format_ptr)++;
1258 error (EXIT_FAILURE, 0, _("missing conversion specifier in suffix"));
1263 error (EXIT_FAILURE, 0,
1264 _("invalid conversion specifier in suffix: %c"), ch);
1266 error (EXIT_FAILURE, 0,
1267 _("invalid conversion specifier in suffix: \\%.3o"), ch);
1272 max_out (char *format)
1274 size_t out_count = 0;
1275 bool percent = false;
1279 if (*format++ != '%')
1281 else if (*format == '%')
1289 error (EXIT_FAILURE, 0,
1290 _("too many %% conversion specifications in suffix"));
1292 out_count += get_format_flags (&format);
1294 size_t width = get_format_width (&format);
1295 size_t prec = get_format_prec (&format);
1297 out_count += MAX (width, prec);
1299 get_format_conv_type (&format);
1304 error (EXIT_FAILURE, 0,
1305 _("missing %% conversion specification in suffix"));
1311 main (int argc, char **argv)
1314 unsigned long int val;
1316 initialize_main (&argc, &argv);
1317 program_name = argv[0];
1318 setlocale (LC_ALL, "");
1319 bindtextdomain (PACKAGE, LOCALEDIR);
1320 textdomain (PACKAGE);
1322 atexit (close_stdout);
1327 suppress_count = false;
1328 remove_files = true;
1329 prefix = DEFAULT_PREFIX;
1331 /* Change the way xmalloc and xrealloc fail. */
1332 xalloc_fail_func = cleanup;
1334 while ((optc = getopt_long (argc, argv, "f:b:kn:sqz", longopts, NULL)) != -1)
1349 remove_files = false;
1353 if (xstrtoul (optarg, NULL, 10, &val, "") != LONGINT_OK
1355 error (EXIT_FAILURE, 0, _("%s: invalid number"), optarg);
1361 suppress_count = true;
1365 elide_empty_files = true;
1368 case_GETOPT_HELP_CHAR;
1370 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1373 usage (EXIT_FAILURE);
1376 if (argc - optind < 2)
1379 error (0, 0, _("missing operand"));
1381 error (0, 0, _("missing operand after %s"), quote (argv[argc - 1]));
1382 usage (EXIT_FAILURE);
1386 filename_space = xmalloc (strlen (prefix) + max_out (suffix) + 2);
1388 filename_space = xmalloc (strlen (prefix) + digits + 2);
1390 set_input_file (argv[optind++]);
1392 parse_patterns (argc, optind, argv);
1396 static int const sig[] = { SIGHUP, SIGINT, SIGQUIT, SIGTERM };
1397 enum { nsigs = sizeof sig / sizeof sig[0] };
1400 struct sigaction act;
1402 sigemptyset (&caught_signals);
1403 for (i = 0; i < nsigs; i++)
1405 sigaction (sig[i], NULL, &act);
1406 if (act.sa_handler != SIG_IGN)
1407 sigaddset (&caught_signals, sig[i]);
1410 act.sa_handler = interrupt_handler;
1411 act.sa_mask = caught_signals;
1414 for (i = 0; i < nsigs; i++)
1415 if (sigismember (&caught_signals, sig[i]))
1416 sigaction (sig[i], &act, NULL);
1418 for (i = 0; i < nsigs; i++)
1419 if (signal (sig[i], SIG_IGN) != SIG_IGN)
1420 signal (sig[i], interrupt_handler);
1426 if (close (input_desc) < 0)
1428 error (0, errno, _("read error"));
1432 exit (EXIT_SUCCESS);
1438 if (status != EXIT_SUCCESS)
1439 fprintf (stderr, _("Try `%s --help' for more information.\n"),
1444 Usage: %s [OPTION]... FILE PATTERN...\n\
1448 Output pieces of FILE separated by PATTERN(s) to files `xx01', `xx02', ...,\n\
1449 and output byte counts of each piece to standard output.\n\
1453 Mandatory arguments to long options are mandatory for short options too.\n\
1456 -b, --suffix-format=FORMAT use sprintf FORMAT instead of %02d\n\
1457 -f, --prefix=PREFIX use PREFIX instead of `xx'\n\
1458 -k, --keep-files do not remove output files on errors\n\
1461 -n, --digits=DIGITS use specified number of digits instead of 2\n\
1462 -s, --quiet, --silent do not print counts of output file sizes\n\
1463 -z, --elide-empty-files remove empty output files\n\
1465 fputs (HELP_OPTION_DESCRIPTION, stdout);
1466 fputs (VERSION_OPTION_DESCRIPTION, stdout);
1469 Read standard input if FILE is -. Each PATTERN may be:\n\
1473 INTEGER copy up to but not including specified line number\n\
1474 /REGEXP/[OFFSET] copy up to but not including a matching line\n\
1475 %REGEXP%[OFFSET] skip to, but not including a matching line\n\
1476 {INTEGER} repeat the previous pattern specified number of times\n\
1477 {*} repeat the previous pattern as many times as possible\n\
1479 A line OFFSET is a required `+' or `-' followed by a positive integer.\n\
1481 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);