1 /* csplit - split a file into sections determined by context lines
2 Copyright (C) 91, 1995-2003 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"
37 /* The official name of this program (e.g., no `g' prefix). */
38 #define PROGRAM_NAME "csplit"
40 #define WRITTEN_BY _("Written by Stuart Kemp and David MacKenzie.")
42 /* Increment size of area for control records. */
45 /* The default prefix for output file names. */
46 #define DEFAULT_PREFIX "xx"
48 /* A compiled pattern arg. */
51 char *regexpr; /* Non-compiled regular expression. */
52 struct re_pattern_buffer re_compiled; /* Compiled regular expression. */
53 intmax_t offset; /* Offset from regexp to split at. */
54 uintmax_t lines_required; /* Number of lines required. */
55 uintmax_t repeat; /* Repeat count. */
56 int argnum; /* ARGV index. */
57 bool repeat_forever; /* True if `*' used as a repeat count. */
58 bool ignore; /* If true, produce no output (for regexp). */
61 /* Initial size of data area in buffers. */
62 #define START_SIZE 8191
64 /* Increment size for data area. */
65 #define INCR_SIZE 2048
67 /* Number of lines kept in each node in line list. */
71 /* Some small values to test the algorithms. */
72 # define START_SIZE 200
77 /* A string with a length count. */
84 /* Pointers to the beginnings of lines in the buffer area.
85 These structures are linked together if needed. */
88 unsigned int used; /* Number of offsets used in this struct. */
89 unsigned int insert_index; /* Next offset to use when inserting line. */
90 unsigned int retrieve_index; /* Next index to use when retrieving line. */
91 struct cstring starts[CTRL_SIZE]; /* Lines in the data area. */
92 struct line *next; /* Next in linked list. */
95 /* The structure to hold the input lines.
96 Contains a pointer to the data area and a list containing
97 pointers to the individual lines. */
100 size_t bytes_alloc; /* Size of the buffer area. */
101 size_t bytes_used; /* Bytes used in the buffer area. */
102 uintmax_t start_line; /* First line number in this buffer. */
103 uintmax_t first_available; /* First line that can be retrieved. */
104 size_t num_lines; /* Number of complete lines in this buffer. */
105 char *buffer; /* Data area. */
106 struct line *line_start; /* Head of list of pointers to lines. */
107 struct line *curr_line; /* The line start record currently in use. */
108 struct buffer_record *next;
111 static void close_output_file (void);
112 static void create_output_file (void);
113 static void delete_all_files (void);
114 static void save_line_to_file (const struct cstring *line);
115 void usage (int status);
117 /* The name this program was run with. */
120 /* Input file descriptor. */
121 static int input_desc = 0;
123 /* Start of buffer list. */
124 static struct buffer_record *head = NULL;
126 /* Partially read line. */
127 static char *hold_area = NULL;
129 /* Number of bytes in `hold_area'. */
130 static size_t hold_count = 0;
132 /* Number of the last line in the buffers. */
133 static uintmax_t last_line_number = 0;
135 /* Number of the line currently being examined. */
136 static uintmax_t current_line = 0;
138 /* If true, we have read EOF. */
139 static bool have_read_eof = false;
141 /* Name of output files. */
142 static char *filename_space = NULL;
144 /* Prefix part of output file names. */
145 static char *prefix = NULL;
147 /* Suffix part of output file names. */
148 static char *suffix = NULL;
150 /* Number of digits to use in output file names. */
151 static int digits = 2;
153 /* Number of files created so far. */
154 static unsigned int files_created = 0;
156 /* Number of bytes written to current file. */
157 static uintmax_t bytes_written;
159 /* Output file pointer. */
160 static FILE *output_stream = NULL;
162 /* Output file name. */
163 static char *output_filename = NULL;
165 /* Perhaps it would be cleaner to pass arg values instead of indexes. */
166 static char **global_argv;
168 /* If true, do not print the count of bytes in each output file. */
169 static bool suppress_count;
171 /* If true, remove output files on error. */
172 static bool remove_files;
174 /* If true, remove all output files which have a zero length. */
175 static bool elide_empty_files;
177 /* The compiled pattern arguments, which determine how to split
179 static struct control *controls;
181 /* Number of elements in `controls'. */
182 static size_t control_used;
184 static struct option const longopts[] =
186 {"digits", required_argument, NULL, 'n'},
187 {"quiet", no_argument, NULL, 'q'},
188 {"silent", no_argument, NULL, 's'},
189 {"keep-files", no_argument, NULL, 'k'},
190 {"elide-empty-files", no_argument, NULL, 'z'},
191 {"prefix", required_argument, NULL, 'f'},
192 {"suffix-format", required_argument, NULL, 'b'},
193 {GETOPT_HELP_OPTION_DECL},
194 {GETOPT_VERSION_OPTION_DECL},
198 /* Optionally remove files created so far; then exit.
199 Called when an error detected. */
204 close_output_file ();
218 interrupt_handler (int sig)
221 struct sigaction sigact;
223 sigact.sa_handler = SIG_DFL;
224 sigemptyset (&sigact.sa_mask);
226 sigaction (sig, &sigact, NULL);
228 signal (sig, SIG_DFL);
234 /* Keep track of NUM bytes of a partial line in buffer START.
235 These bytes will be retrieved later when another large buffer is read.
236 It is not necessary to create a new buffer for these bytes; instead,
237 we keep a pointer to the existing buffer. This buffer *is* on the
238 free list, and when the next buffer is obtained from this list
239 (even if it is this one), these bytes will be placed at the
240 start of the new buffer. */
243 save_to_hold_area (char *start, size_t num)
249 /* Read up to MAX_N_BYTES bytes from the input stream into DEST.
250 Return the number of bytes read. */
253 read_input (char *dest, size_t max_n_bytes)
257 if (max_n_bytes == 0)
260 bytes_read = safe_read (input_desc, dest, max_n_bytes);
263 have_read_eof = true;
265 if (bytes_read == SAFE_READ_ERROR)
267 error (0, errno, _("read error"));
274 /* Initialize existing line record P. */
277 clear_line_control (struct line *p)
281 p->retrieve_index = 0;
284 /* Return a new, initialized line record. */
287 new_line_control (void)
289 struct line *p = xmalloc (sizeof *p);
292 clear_line_control (p);
297 /* Record LINE_START, which is the address of the start of a line
298 of length LINE_LEN in the large buffer, in the lines buffer of B. */
301 keep_new_line (struct buffer_record *b, char *line_start, size_t line_len)
305 /* If there is no existing area to keep line info, get some. */
306 if (b->line_start == NULL)
307 b->line_start = b->curr_line = new_line_control ();
309 /* If existing area for lines is full, get more. */
310 if (b->curr_line->used == CTRL_SIZE)
312 b->curr_line->next = new_line_control ();
313 b->curr_line = b->curr_line->next;
318 /* Record the start of the line, and update counters. */
319 l->starts[l->insert_index].str = line_start;
320 l->starts[l->insert_index].len = line_len;
325 /* Scan the buffer in B for newline characters
326 and record the line start locations and lengths in B.
327 Return the number of lines found in this buffer.
329 There may be an incomplete line at the end of the buffer;
330 a pointer is kept to this area, which will be used when
331 the next buffer is filled. */
334 record_line_starts (struct buffer_record *b)
336 char *line_start; /* Start of current line. */
337 char *line_end; /* End of each line found. */
338 size_t bytes_left; /* Length of incomplete last line. */
339 size_t lines; /* Number of lines found. */
340 size_t line_length; /* Length of each line found. */
342 if (b->bytes_used == 0)
346 line_start = b->buffer;
347 bytes_left = b->bytes_used;
351 line_end = memchr (line_start, '\n', bytes_left);
352 if (line_end == NULL)
354 line_length = line_end - line_start + 1;
355 keep_new_line (b, line_start, line_length);
356 bytes_left -= line_length;
357 line_start = line_end + 1;
361 /* Check for an incomplete last line. */
366 keep_new_line (b, line_start, bytes_left);
370 save_to_hold_area (line_start, bytes_left);
373 b->num_lines = lines;
374 b->first_available = b->start_line = last_line_number + 1;
375 last_line_number += lines;
380 /* Return a new buffer with room to store SIZE bytes, plus
381 an extra byte for safety. */
383 static struct buffer_record *
384 create_new_buffer (size_t size)
386 struct buffer_record *new_buffer = xmalloc (sizeof *new_buffer);
388 new_buffer->buffer = xmalloc (size + 1);
390 new_buffer->bytes_alloc = size;
391 new_buffer->line_start = new_buffer->curr_line = NULL;
396 /* Return a new buffer of at least MINSIZE bytes. If a buffer of at
397 least that size is currently free, use it, otherwise create a new one. */
399 static struct buffer_record *
400 get_new_buffer (size_t min_size)
402 struct buffer_record *new_buffer; /* Buffer to return. */
403 size_t alloc_size; /* Actual size that will be requested. */
405 alloc_size = START_SIZE;
406 if (alloc_size < min_size)
408 size_t s = min_size - alloc_size + INCR_SIZE - 1;
409 alloc_size += s - s % INCR_SIZE;
412 new_buffer = create_new_buffer (alloc_size);
414 new_buffer->num_lines = 0;
415 new_buffer->bytes_used = 0;
416 new_buffer->start_line = new_buffer->first_available = last_line_number + 1;
417 new_buffer->next = NULL;
423 free_buffer (struct buffer_record *buf)
428 /* Append buffer BUF to the linked list of buffers that contain
429 some data yet to be processed. */
432 save_buffer (struct buffer_record *buf)
434 struct buffer_record *p;
437 buf->curr_line = buf->line_start;
443 for (p = head; p->next; p = p->next)
449 /* Fill a buffer of input.
451 Set the initial size of the buffer to a default.
452 Fill the buffer (from the hold area and input stream)
453 and find the individual lines.
454 If no lines are found (the buffer is too small to hold the next line),
455 release the current buffer (whose contents would have been put in the
456 hold area) and repeat the process with another large buffer until at least
457 one entire line has been read.
459 Return true if a new buffer was obtained, otherwise false
460 (in which case end-of-file must have been encountered). */
465 struct buffer_record *b;
466 size_t bytes_wanted = START_SIZE; /* Minimum buffer size. */
467 size_t bytes_avail; /* Size of new buffer created. */
468 size_t lines_found; /* Number of lines in this new buffer. */
469 char *p; /* Place to load into buffer. */
474 /* We must make the buffer at least as large as the amount of data
475 in the partial line left over from the last call. */
476 if (bytes_wanted < hold_count)
477 bytes_wanted = hold_count;
481 b = get_new_buffer (bytes_wanted);
482 bytes_avail = b->bytes_alloc; /* Size of buffer returned. */
485 /* First check the `holding' area for a partial line. */
489 memcpy (p, hold_area, hold_count);
491 b->bytes_used += hold_count;
492 bytes_avail -= hold_count;
496 b->bytes_used += read_input (p, bytes_avail);
498 lines_found = record_line_starts (b);
499 bytes_wanted = b->bytes_alloc * 2;
503 while (!lines_found && !have_read_eof);
508 return lines_found != 0;
511 /* Return the line number of the first line that has not yet been retrieved. */
514 get_first_line_in_buffer (void)
516 if (head == NULL && !load_buffer ())
517 error (EXIT_FAILURE, errno, _("input disappeared"));
519 return head->first_available;
522 /* Return a pointer to the logical first line in the buffer and make the
523 next line the logical first line.
524 Return NULL if there is no more input. */
526 static struct cstring *
529 struct cstring *line; /* Return value. */
530 struct line *l; /* For convenience. */
532 if (head == NULL && !load_buffer ())
535 if (current_line < head->first_available)
536 current_line = head->first_available;
538 ++(head->first_available);
542 line = &l->starts[l->retrieve_index];
544 /* Advance index to next line. */
545 if (++l->retrieve_index == l->used)
547 /* Go on to the next line record. */
548 head->curr_line = l->next;
549 if (head->curr_line == NULL || head->curr_line->used == 0)
551 /* Go on to the next data block. */
552 struct buffer_record *b = head;
561 /* Search the buffers for line LINENUM, reading more input if necessary.
562 Return a pointer to the line, or NULL if it is not found in the file. */
564 static struct cstring *
565 find_line (uintmax_t linenum)
567 struct buffer_record *b;
569 if (head == NULL && !load_buffer ())
572 if (linenum < head->start_line)
577 if (linenum < b->start_line + b->num_lines)
579 /* The line is in this buffer. */
581 size_t offset; /* How far into the buffer the line is. */
584 offset = linenum - b->start_line;
585 /* Find the control record. */
586 while (offset >= CTRL_SIZE)
591 return &l->starts[offset];
593 if (b->next == NULL && !load_buffer ())
595 b = b->next; /* Try the next data block. */
599 /* Return true if at least one more line is available for input. */
604 return find_line (current_line + 1) == NULL;
607 /* Set the name of the input file to NAME and open it. */
610 set_input_file (const char *name)
612 if (STREQ (name, "-"))
616 input_desc = open (name, O_RDONLY);
618 error (EXIT_FAILURE, errno, "%s", name);
622 /* Write all lines from the beginning of the buffer up to, but
623 not including, line LAST_LINE, to the current output file.
624 If IGNORE is true, do not output lines selected here.
625 ARGNUM is the index in ARGV of the current pattern. */
628 write_to_file (uintmax_t last_line, bool ignore, int argnum)
630 struct cstring *line;
631 uintmax_t first_line; /* First available input line. */
632 uintmax_t lines; /* Number of lines to output. */
635 first_line = get_first_line_in_buffer ();
637 if (first_line > last_line)
639 error (0, 0, _("%s: line number out of range"), global_argv[argnum]);
643 lines = last_line - first_line;
645 for (i = 0; i < lines; i++)
647 line = remove_line ();
650 error (0, 0, _("%s: line number out of range"), global_argv[argnum]);
654 save_line_to_file (line);
658 /* Output any lines left after all regexps have been processed. */
661 dump_rest_of_file (void)
663 struct cstring *line;
665 while ((line = remove_line ()) != NULL)
666 save_line_to_file (line);
669 /* Handle an attempt to read beyond EOF under the control of record P,
670 on iteration REPETITION if nonzero. */
673 handle_line_error (const struct control *p, uintmax_t repetition)
675 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
677 fprintf (stderr, _("%s: `%s': line number out of range"),
678 program_name, umaxtostr (p->lines_required, buf));
680 fprintf (stderr, _(" on repetition %s\n"), umaxtostr (repetition, buf));
682 fprintf (stderr, "\n");
687 /* Determine the line number that marks the end of this file,
688 then get those lines and save them to the output file.
689 P is the control record.
690 REPETITION is the repetition number. */
693 process_line_count (const struct control *p, uintmax_t repetition)
696 uintmax_t last_line_to_save = p->lines_required * (repetition + 1);
697 struct cstring *line;
699 create_output_file ();
701 linenum = get_first_line_in_buffer ();
703 while (linenum++ < last_line_to_save)
705 line = remove_line ();
707 handle_line_error (p, repetition);
708 save_line_to_file (line);
711 close_output_file ();
713 /* Ensure that the line number specified is not 1 greater than
714 the number of lines in the file. */
715 if (no_more_lines ())
716 handle_line_error (p, repetition);
720 regexp_error (struct control *p, uintmax_t repetition, bool ignore)
722 fprintf (stderr, _("%s: `%s': match not found"),
723 program_name, global_argv[p->argnum]);
727 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
728 fprintf (stderr, _(" on repetition %s\n"), umaxtostr (repetition, buf));
731 fprintf (stderr, "\n");
735 dump_rest_of_file ();
736 close_output_file ();
741 /* Read the input until a line matches the regexp in P, outputting
742 it unless P->IGNORE is true.
743 REPETITION is this repeat-count; 0 means the first time. */
746 process_regexp (struct control *p, uintmax_t repetition)
748 struct cstring *line; /* From input file. */
749 size_t line_len; /* To make "$" in regexps work. */
750 uintmax_t break_line; /* First line number of next file. */
751 bool ignore = p->ignore; /* If true, skip this section. */
755 create_output_file ();
757 /* If there is no offset for the regular expression, or
758 it is positive, then it is not necessary to buffer the lines. */
764 line = find_line (++current_line);
767 if (p->repeat_forever)
771 dump_rest_of_file ();
772 close_output_file ();
777 regexp_error (p, repetition, ignore);
779 line_len = line->len;
780 if (line->str[line_len - 1] == '\n')
782 ret = re_search (&p->re_compiled, line->str, line_len,
786 error (0, 0, _("error in regular expression search"));
791 line = remove_line ();
793 save_line_to_file (line);
801 /* Buffer the lines. */
804 line = find_line (++current_line);
807 if (p->repeat_forever)
811 dump_rest_of_file ();
812 close_output_file ();
817 regexp_error (p, repetition, ignore);
819 line_len = line->len;
820 if (line->str[line_len - 1] == '\n')
822 ret = re_search (&p->re_compiled, line->str, line_len,
826 error (0, 0, _("error in regular expression search"));
834 /* Account for any offset from this regexp. */
835 break_line = current_line + p->offset;
837 write_to_file (break_line, ignore, p->argnum);
840 close_output_file ();
843 current_line = break_line;
846 /* Split the input file according to the control records we have built. */
853 for (i = 0; i < control_used; i++)
856 if (controls[i].regexpr)
858 for (j = 0; (controls[i].repeat_forever
859 || j <= controls[i].repeat); j++)
860 process_regexp (&controls[i], j);
864 for (j = 0; (controls[i].repeat_forever
865 || j <= controls[i].repeat); j++)
866 process_line_count (&controls[i], j);
870 create_output_file ();
871 dump_rest_of_file ();
872 close_output_file ();
875 /* Return the name of output file number NUM. */
878 make_filename (unsigned int num)
880 strcpy (filename_space, prefix);
882 sprintf (filename_space+strlen(prefix), suffix, num);
884 sprintf (filename_space+strlen(prefix), "%0*u", digits, num);
885 return filename_space;
888 /* Create the next output file. */
891 create_output_file (void)
893 output_filename = make_filename (files_created);
894 output_stream = fopen (output_filename, "w");
895 if (output_stream == NULL)
897 error (0, errno, "%s", output_filename);
904 /* Delete all the files we have created. */
907 delete_all_files (void)
911 for (i = 0; i < files_created; i++)
913 const char *name = make_filename (i);
915 error (0, errno, "%s", name);
919 /* Close the current output file and print the count
920 of characters in this file. */
923 close_output_file (void)
927 if (ferror (output_stream))
929 error (0, 0, _("write error for `%s'"), output_filename);
930 output_stream = NULL;
933 if (fclose (output_stream) != 0)
935 error (0, errno, "%s", output_filename);
936 output_stream = NULL;
939 if (bytes_written == 0 && elide_empty_files)
941 if (unlink (output_filename))
942 error (0, errno, "%s", output_filename);
947 /* FIXME: if we write to stdout here, we have to close stdout
948 and check for errors. */
951 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
952 fprintf (stdout, "%s\n", umaxtostr (bytes_written, buf));
955 output_stream = NULL;
959 /* Save line LINE to the output file and
960 increment the character count for the current file. */
963 save_line_to_file (const struct cstring *line)
965 fwrite (line->str, sizeof (char), line->len, output_stream);
966 bytes_written += line->len;
969 /* Return a new, initialized control record. */
971 static struct control *
972 new_control_record (void)
974 static size_t control_allocated = 0; /* Total space allocated. */
977 if (control_used == control_allocated)
979 control_allocated += ALLOC_SIZE;
980 controls = xrealloc (controls, control_allocated * sizeof *controls);
982 p = &controls[control_used++];
985 p->repeat_forever = false;
986 p->lines_required = 0;
991 /* Check if there is a numeric offset after a regular expression.
992 STR is the entire command line argument.
993 P is the control record for this regular expression.
994 NUM is the numeric part of STR. */
997 check_for_offset (struct control *p, const char *str, const char *num)
999 if (xstrtoimax (num, NULL, 10, &p->offset, "") != LONGINT_OK)
1000 error (EXIT_FAILURE, 0, _("%s: integer expected after delimiter"), str);
1003 /* Given that the first character of command line arg STR is '{',
1004 make sure that the rest of the string is a valid repeat count
1005 and store its value in P.
1006 ARGNUM is the ARGV index of STR. */
1009 parse_repeat_count (int argnum, struct control *p, char *str)
1014 end = str + strlen (str) - 1;
1016 error (EXIT_FAILURE, 0, _("%s: `}' is required in repeat count"), str);
1019 if (str+1 == end-1 && *(str+1) == '*')
1020 p->repeat_forever = true;
1023 if (xstrtoumax (str + 1, NULL, 10, &val, "") != LONGINT_OK)
1025 error (EXIT_FAILURE, 0,
1026 _("%s}: integer required between `{' and `}'"),
1027 global_argv[argnum]);
1035 /* Extract the regular expression from STR and check for a numeric offset.
1036 STR should start with the regexp delimiter character.
1037 Return a new control record for the regular expression.
1038 ARGNUM is the ARGV index of STR.
1039 Unless IGNORE is true, mark these lines for output. */
1041 static struct control *
1042 extract_regexp (int argnum, bool ignore, char *str)
1044 size_t len; /* Number of bytes in this regexp. */
1046 char *closing_delim;
1050 closing_delim = strrchr (str + 1, delim);
1051 if (closing_delim == NULL)
1052 error (EXIT_FAILURE, 0,
1053 _("%s: closing delimiter `%c' missing"), str, delim);
1055 len = closing_delim - str - 1;
1056 p = new_control_record ();
1060 p->regexpr = xmalloc (len + 1);
1061 strncpy (p->regexpr, str + 1, len);
1062 p->re_compiled.allocated = len * 2;
1063 p->re_compiled.buffer = xmalloc (p->re_compiled.allocated);
1064 p->re_compiled.fastmap = xmalloc (1 << CHAR_BIT);
1065 p->re_compiled.translate = 0;
1066 err = re_compile_pattern (p->regexpr, len, &p->re_compiled);
1069 error (0, 0, _("%s: invalid regular expression: %s"), str, err);
1073 if (closing_delim[1])
1074 check_for_offset (p, str, closing_delim + 1);
1079 /* Extract the break patterns from args START through ARGC - 1 of ARGV.
1080 After each pattern, check if the next argument is a repeat count. */
1083 parse_patterns (int argc, int start, char **argv)
1085 int i; /* Index into ARGV. */
1086 struct control *p; /* New control record created. */
1088 static uintmax_t last_val = 0;
1090 for (i = start; i < argc; i++)
1092 if (*argv[i] == '/' || *argv[i] == '%')
1094 p = extract_regexp (i, *argv[i] == '%', argv[i]);
1098 p = new_control_record ();
1101 if (xstrtoumax (argv[i], NULL, 10, &val, "") != LONGINT_OK)
1102 error (EXIT_FAILURE, 0, _("%s: invalid pattern"), argv[i]);
1104 error (EXIT_FAILURE, 0,
1105 _("%s: line number must be greater than zero"),
1109 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
1110 error (EXIT_FAILURE, 0,
1111 _("line number `%s' is smaller than preceding line number, %s"),
1112 argv[i], umaxtostr (last_val, buf));
1115 if (val == last_val)
1117 _("warning: line number `%s' is the same as preceding line number"),
1122 p->lines_required = val;
1125 if (i + 1 < argc && *argv[i + 1] == '{')
1127 /* We have a repeat count. */
1129 parse_repeat_count (i, p, argv[i]);
1135 get_format_flags (char **format_ptr)
1137 unsigned int count = 0;
1139 for (; **format_ptr; (*format_ptr)++)
1141 switch (**format_ptr)
1152 count |= 2; /* Allow for 0x prefix preceding an `x' conversion. */
1163 get_format_width (char **format_ptr)
1165 unsigned long int val = 0;
1167 if (ISDIGIT (**format_ptr)
1168 && (xstrtoul (*format_ptr, format_ptr, 10, &val, NULL) != LONGINT_OK
1170 error (EXIT_FAILURE, 0, _("invalid format width"));
1172 /* Allow for enough octal digits to represent the value of UINT_MAX,
1173 even if the field width is less than that. */
1174 return MAX (val, (sizeof (unsigned int) * CHAR_BIT + 2) / 3);
1178 get_format_prec (char **format_ptr)
1180 if (**format_ptr != '.')
1184 if (! ISDIGIT (**format_ptr))
1188 unsigned long int val;
1189 if (xstrtoul (*format_ptr, format_ptr, 10, &val, NULL) != LONGINT_OK
1191 error (EXIT_FAILURE, 0, _("invalid format precision"));
1197 get_format_conv_type (char **format_ptr)
1199 unsigned char ch = *(*format_ptr)++;
1212 error (EXIT_FAILURE, 0, _("missing conversion specifier in suffix"));
1217 error (EXIT_FAILURE, 0,
1218 _("invalid conversion specifier in suffix: %c"), ch);
1220 error (EXIT_FAILURE, 0,
1221 _("invalid conversion specifier in suffix: \\%.3o"), ch);
1226 max_out (char *format)
1228 size_t out_count = 0;
1229 bool percent = false;
1233 if (*format++ != '%')
1235 else if (*format == '%')
1243 error (EXIT_FAILURE, 0,
1244 _("too many %% conversion specifications in suffix"));
1246 out_count += get_format_flags (&format);
1248 size_t width = get_format_width (&format);
1249 size_t prec = get_format_prec (&format);
1251 out_count += MAX (width, prec);
1253 get_format_conv_type (&format);
1258 error (EXIT_FAILURE, 0,
1259 _("missing %% conversion specification in suffix"));
1265 main (int argc, char **argv)
1268 unsigned long int val;
1270 struct sigaction oldact, newact;
1273 initialize_main (&argc, &argv);
1274 program_name = argv[0];
1275 setlocale (LC_ALL, "");
1276 bindtextdomain (PACKAGE, LOCALEDIR);
1277 textdomain (PACKAGE);
1279 atexit (close_stdout);
1284 suppress_count = false;
1285 remove_files = true;
1286 prefix = DEFAULT_PREFIX;
1288 /* Change the way xmalloc and xrealloc fail. */
1289 xalloc_fail_func = cleanup;
1292 newact.sa_handler = interrupt_handler;
1293 sigemptyset (&newact.sa_mask);
1294 newact.sa_flags = 0;
1296 sigaction (SIGHUP, NULL, &oldact);
1297 if (oldact.sa_handler != SIG_IGN)
1298 sigaction (SIGHUP, &newact, NULL);
1300 sigaction (SIGINT, NULL, &oldact);
1301 if (oldact.sa_handler != SIG_IGN)
1302 sigaction (SIGINT, &newact, NULL);
1304 sigaction (SIGQUIT, NULL, &oldact);
1305 if (oldact.sa_handler != SIG_IGN)
1306 sigaction (SIGQUIT, &newact, NULL);
1308 sigaction (SIGTERM, NULL, &oldact);
1309 if (oldact.sa_handler != SIG_IGN)
1310 sigaction (SIGTERM, &newact, NULL);
1312 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
1313 signal (SIGHUP, interrupt_handler);
1314 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
1315 signal (SIGINT, interrupt_handler);
1316 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
1317 signal (SIGQUIT, interrupt_handler);
1318 if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
1319 signal (SIGTERM, interrupt_handler);
1322 while ((optc = getopt_long (argc, argv, "f:b:kn:sqz", longopts, NULL)) != -1)
1337 remove_files = false;
1341 if (xstrtoul (optarg, NULL, 10, &val, "") != LONGINT_OK
1343 error (EXIT_FAILURE, 0, _("%s: invalid number"), optarg);
1349 suppress_count = true;
1353 elide_empty_files = true;
1356 case_GETOPT_HELP_CHAR;
1358 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, WRITTEN_BY);
1361 usage (EXIT_FAILURE);
1364 if (argc - optind < 2)
1366 error (0, 0, _("too few arguments"));
1367 usage (EXIT_FAILURE);
1371 filename_space = xmalloc (strlen (prefix) + max_out (suffix) + 2);
1373 filename_space = xmalloc (strlen (prefix) + digits + 2);
1375 set_input_file (argv[optind++]);
1377 parse_patterns (argc, optind, argv);
1381 if (close (input_desc) < 0)
1383 error (0, errno, _("read error"));
1387 exit (EXIT_SUCCESS);
1394 fprintf (stderr, _("Try `%s --help' for more information.\n"),
1399 Usage: %s [OPTION]... FILE PATTERN...\n\
1403 Output pieces of FILE separated by PATTERN(s) to files `xx01', `xx02', ...,\n\
1404 and output byte counts of each piece to standard output.\n\
1408 Mandatory arguments to long options are mandatory for short options too.\n\
1411 -b, --suffix-format=FORMAT use sprintf FORMAT instead of %02d\n\
1412 -f, --prefix=PREFIX use PREFIX instead of `xx'\n\
1413 -k, --keep-files do not remove output files on errors\n\
1416 -n, --digits=DIGITS use specified number of digits instead of 2\n\
1417 -s, --quiet, --silent do not print counts of output file sizes\n\
1418 -z, --elide-empty-files remove empty output files\n\
1420 fputs (HELP_OPTION_DESCRIPTION, stdout);
1421 fputs (VERSION_OPTION_DESCRIPTION, stdout);
1424 Read standard input if FILE is -. Each PATTERN may be:\n\
1428 INTEGER copy up to but not including specified line number\n\
1429 /REGEXP/[OFFSET] copy up to but not including a matching line\n\
1430 %REGEXP%[OFFSET] skip to, but not including a matching line\n\
1431 {INTEGER} repeat the previous pattern specified number of times\n\
1432 {*} repeat the previous pattern as many times as possible\n\
1434 A line OFFSET is a required `+' or `-' followed by a positive integer.\n\
1436 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
1438 exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);