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.")
47 /* Increment size of area for control records. */
50 /* The default prefix for output file names. */
51 #define DEFAULT_PREFIX "xx"
55 /* A compiled pattern arg. */
58 char *regexpr; /* Non-compiled regular expression. */
59 struct re_pattern_buffer re_compiled; /* Compiled regular expression. */
60 int offset; /* Offset from regexp to split at. */
61 uintmax_t lines_required; /* Number of lines required. */
62 uintmax_t repeat; /* Repeat count. */
63 int repeat_forever; /* Non-zero if `*' used as a repeat count. */
64 int argnum; /* ARGV index. */
65 boolean ignore; /* If true, produce no output (for regexp). */
68 /* Initial size of data area in buffers. */
69 #define START_SIZE 8191
71 /* Increment size for data area. */
72 #define INCR_SIZE 2048
74 /* Number of lines kept in each node in line list. */
78 /* Some small values to test the algorithms. */
79 # define START_SIZE 200
84 /* A string with a length count. */
91 /* Pointers to the beginnings of lines in the buffer area.
92 These structures are linked together if needed. */
95 unsigned used; /* Number of offsets used in this struct. */
96 unsigned insert_index; /* Next offset to use when inserting line. */
97 unsigned retrieve_index; /* Next index to use when retrieving line. */
98 struct cstring starts[CTRL_SIZE]; /* Lines in the data area. */
99 struct line *next; /* Next in linked list. */
102 /* The structure to hold the input lines.
103 Contains a pointer to the data area and a list containing
104 pointers to the individual lines. */
107 unsigned bytes_alloc; /* Size of the buffer area. */
108 unsigned bytes_used; /* Bytes used in the buffer area. */
109 unsigned start_line; /* First line number in this buffer. */
110 unsigned first_available; /* First line that can be retrieved. */
111 unsigned num_lines; /* Number of complete lines in this buffer. */
112 char *buffer; /* Data area. */
113 struct line *line_start; /* Head of list of pointers to lines. */
114 struct line *curr_line; /* The line start record currently in use. */
115 struct buffer_record *next;
118 static void close_output_file (void);
119 static void create_output_file (void);
120 static void delete_all_files (void);
121 static void save_line_to_file (const struct cstring *line);
122 void usage (int status);
124 /* The name this program was run with. */
127 /* Convert the number of 8-bit bytes of a binary representation to
128 the number of characters required to represent the same quantity
129 as an unsigned octal. For example, a 32-bit (4-byte) quantity may
130 require a field width as wide as 11 characters. */
131 static const unsigned int bytes_to_octal_digits[] =
132 {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};
134 /* Input file descriptor. */
135 static int input_desc = 0;
137 /* List of available buffers. */
138 static struct buffer_record *free_list = NULL;
140 /* Start of buffer list. */
141 static struct buffer_record *head = NULL;
143 /* Partially read line. */
144 static char *hold_area = NULL;
146 /* Number of chars in `hold_area'. */
147 static unsigned hold_count = 0;
149 /* Number of the last line in the buffers. */
150 static unsigned last_line_number = 0;
152 /* Number of the line currently being examined. */
153 static unsigned current_line = 0;
155 /* If TRUE, we have read EOF. */
156 static boolean have_read_eof = FALSE;
158 /* Name of output files. */
159 static char *filename_space = NULL;
161 /* Prefix part of output file names. */
162 static char *prefix = NULL;
164 /* Suffix part of output file names. */
165 static char *suffix = NULL;
167 /* Number of digits to use in output file names. */
168 static int digits = 2;
170 /* Number of files created so far. */
171 static unsigned int files_created = 0;
173 /* Number of bytes written to current file. */
174 static unsigned int bytes_written;
176 /* Output file pointer. */
177 static FILE *output_stream = NULL;
179 /* Output file name. */
180 static char *output_filename = NULL;
182 /* Perhaps it would be cleaner to pass arg values instead of indexes. */
183 static char **global_argv;
185 /* If TRUE, do not print the count of bytes in each output file. */
186 static boolean suppress_count;
188 /* If TRUE, remove output files on error. */
189 static boolean remove_files;
191 /* If TRUE, remove all output files which have a zero length. */
192 static boolean elide_empty_files;
194 /* The compiled pattern arguments, which determine how to split
196 static struct control *controls;
198 /* Number of elements in `controls'. */
199 static unsigned int control_used;
201 static struct option const longopts[] =
203 {"digits", required_argument, NULL, 'n'},
204 {"quiet", no_argument, NULL, 'q'},
205 {"silent", no_argument, NULL, 's'},
206 {"keep-files", no_argument, NULL, 'k'},
207 {"elide-empty-files", no_argument, NULL, 'z'},
208 {"prefix", required_argument, NULL, 'f'},
209 {"suffix-format", required_argument, NULL, 'b'},
210 {GETOPT_HELP_OPTION_DECL},
211 {GETOPT_VERSION_OPTION_DECL},
215 /* Optionally remove files created so far; then exit.
216 Called when an error detected. */
222 close_output_file ();
236 interrupt_handler (int sig)
239 struct sigaction sigact;
241 sigact.sa_handler = SIG_DFL;
242 sigemptyset (&sigact.sa_mask);
244 sigaction (sig, &sigact, NULL);
246 signal (sig, SIG_DFL);
252 /* Keep track of NUM chars of a partial line in buffer START.
253 These chars will be retrieved later when another large buffer is read.
254 It is not necessary to create a new buffer for these chars; instead,
255 we keep a pointer to the existing buffer. This buffer *is* on the
256 free list, and when the next buffer is obtained from this list
257 (even if it is this one), these chars will be placed at the
258 start of the new buffer. */
261 save_to_hold_area (char *start, unsigned int num)
267 /* Read up to MAX_N_BYTES chars from the input stream into DEST.
268 Return the number of chars read. */
269 /* FIXME: MAX_N_BYTES should be of type size_t, but if you pull
270 that thread, you'll find there are many other `unsigned' types
271 in this file that should also be changed. */
274 read_input (char *dest, int max_n_bytes)
278 if (max_n_bytes == 0)
281 bytes_read = safe_read (input_desc, dest, max_n_bytes);
284 have_read_eof = TRUE;
286 if (bytes_read == SAFE_READ_ERROR)
288 error (0, errno, _("read error"));
295 /* Initialize existing line record P. */
298 clear_line_control (struct line *p)
302 p->retrieve_index = 0;
305 /* Initialize all line records in B. */
308 clear_all_line_control (struct buffer_record *b)
312 for (l = b->line_start; l; l = l->next)
313 clear_line_control (l);
316 /* Return a new, initialized line record. */
319 new_line_control (void)
323 p = xmalloc (sizeof (struct line));
326 clear_line_control (p);
331 /* Record LINE_START, which is the address of the start of a line
332 of length LINE_LEN in the large buffer, in the lines buffer of B. */
335 keep_new_line (struct buffer_record *b, char *line_start, int line_len)
339 /* If there is no existing area to keep line info, get some. */
340 if (b->line_start == NULL)
341 b->line_start = b->curr_line = new_line_control ();
343 /* If existing area for lines is full, get more. */
344 if (b->curr_line->used == CTRL_SIZE)
346 b->curr_line->next = new_line_control ();
347 b->curr_line = b->curr_line->next;
352 /* Record the start of the line, and update counters. */
353 l->starts[l->insert_index].str = line_start;
354 l->starts[l->insert_index].len = line_len;
359 /* Scan the buffer in B for newline characters
360 and record the line start locations and lengths in B.
361 Return the number of lines found in this buffer.
363 There may be an incomplete line at the end of the buffer;
364 a pointer is kept to this area, which will be used when
365 the next buffer is filled. */
368 record_line_starts (struct buffer_record *b)
370 char *line_start; /* Start of current line. */
371 char *line_end; /* End of each line found. */
372 unsigned int bytes_left; /* Length of incomplete last line. */
373 unsigned int lines; /* Number of lines found. */
374 unsigned int line_length; /* Length of each line found. */
376 if (b->bytes_used == 0)
380 line_start = b->buffer;
381 bytes_left = b->bytes_used;
385 line_end = memchr (line_start, '\n', bytes_left);
386 if (line_end == NULL)
388 line_length = line_end - line_start + 1;
389 keep_new_line (b, line_start, line_length);
390 bytes_left -= line_length;
391 line_start = line_end + 1;
395 /* Check for an incomplete last line. */
400 keep_new_line (b, line_start, bytes_left);
404 save_to_hold_area (line_start, bytes_left);
407 b->num_lines = lines;
408 b->first_available = b->start_line = last_line_number + 1;
409 last_line_number += lines;
414 /* Return a new buffer with room to store SIZE bytes, plus
415 an extra byte for safety. */
417 static struct buffer_record *
418 create_new_buffer (unsigned int size)
420 struct buffer_record *new_buffer;
422 new_buffer = (struct buffer_record *)
423 xmalloc (sizeof (struct buffer_record));
425 new_buffer->buffer = xmalloc (size + 1);
427 new_buffer->bytes_alloc = size;
428 new_buffer->line_start = new_buffer->curr_line = NULL;
433 /* Return a new buffer of at least MINSIZE bytes. If a buffer of at
434 least that size is currently free, use it, otherwise create a new one. */
436 static struct buffer_record *
437 get_new_buffer (unsigned int min_size)
439 struct buffer_record *p, *q;
440 struct buffer_record *new_buffer; /* Buffer to return. */
441 unsigned int alloc_size; /* Actual size that will be requested. */
443 alloc_size = START_SIZE;
444 while (min_size > alloc_size)
445 alloc_size += INCR_SIZE;
447 if (free_list == NULL)
448 new_buffer = create_new_buffer (alloc_size);
451 /* Use first-fit to find a buffer. */
452 p = new_buffer = NULL;
457 if (q->bytes_alloc >= min_size)
470 new_buffer = (q ? q : create_new_buffer (alloc_size));
472 new_buffer->curr_line = new_buffer->line_start;
473 clear_all_line_control (new_buffer);
476 new_buffer->num_lines = 0;
477 new_buffer->bytes_used = 0;
478 new_buffer->start_line = new_buffer->first_available = last_line_number + 1;
479 new_buffer->next = NULL;
484 /* Add buffer BUF to the list of free buffers. */
487 free_buffer (struct buffer_record *buf)
489 buf->next = free_list;
493 /* Append buffer BUF to the linked list of buffers that contain
494 some data yet to be processed. */
497 save_buffer (struct buffer_record *buf)
499 struct buffer_record *p;
502 buf->curr_line = buf->line_start;
508 for (p = head; p->next; p = p->next)
514 /* Fill a buffer of input.
516 Set the initial size of the buffer to a default.
517 Fill the buffer (from the hold area and input stream)
518 and find the individual lines.
519 If no lines are found (the buffer is too small to hold the next line),
520 release the current buffer (whose contents would have been put in the
521 hold area) and repeat the process with another large buffer until at least
522 one entire line has been read.
524 Return TRUE if a new buffer was obtained, otherwise false
525 (in which case end-of-file must have been encountered). */
530 struct buffer_record *b;
531 unsigned int bytes_wanted = START_SIZE; /* Minimum buffer size. */
532 unsigned int bytes_avail; /* Size of new buffer created. */
533 unsigned int lines_found; /* Number of lines in this new buffer. */
534 char *p; /* Place to load into buffer. */
539 /* We must make the buffer at least as large as the amount of data
540 in the partial line left over from the last call. */
541 if (bytes_wanted < hold_count)
542 bytes_wanted = hold_count;
546 b = get_new_buffer (bytes_wanted);
547 bytes_avail = b->bytes_alloc; /* Size of buffer returned. */
550 /* First check the `holding' area for a partial line. */
554 memcpy (p, hold_area, hold_count);
556 b->bytes_used += hold_count;
557 bytes_avail -= hold_count;
561 b->bytes_used += (unsigned int) read_input (p, bytes_avail);
563 lines_found = record_line_starts (b);
564 bytes_wanted = b->bytes_alloc * 2;
568 while (!lines_found && !have_read_eof);
573 return lines_found != 0;
576 /* Return the line number of the first line that has not yet been retrieved. */
579 get_first_line_in_buffer (void)
581 if (head == NULL && !load_buffer ())
582 error (EXIT_FAILURE, errno, _("input disappeared"));
584 return head->first_available;
587 /* Return a pointer to the logical first line in the buffer and make the
588 next line the logical first line.
589 Return NULL if there is no more input. */
591 static struct cstring *
594 struct cstring *line; /* Return value. */
595 struct line *l; /* For convenience. */
597 if (head == NULL && !load_buffer ())
600 if (current_line < head->first_available)
601 current_line = head->first_available;
603 ++(head->first_available);
607 line = &l->starts[l->retrieve_index];
609 /* Advance index to next line. */
610 if (++l->retrieve_index == l->used)
612 /* Go on to the next line record. */
613 head->curr_line = l->next;
614 if (head->curr_line == NULL || head->curr_line->used == 0)
616 /* Go on to the next data block. */
617 struct buffer_record *b = head;
626 /* Search the buffers for line LINENUM, reading more input if necessary.
627 Return a pointer to the line, or NULL if it is not found in the file. */
629 static struct cstring *
630 find_line (unsigned int linenum)
632 struct buffer_record *b;
634 if (head == NULL && !load_buffer ())
637 if (linenum < head->start_line)
642 if (linenum < b->start_line + b->num_lines)
644 /* The line is in this buffer. */
646 unsigned int offset; /* How far into the buffer the line is. */
649 offset = linenum - b->start_line;
650 /* Find the control record. */
651 while (offset >= CTRL_SIZE)
656 return &l->starts[offset];
658 if (b->next == NULL && !load_buffer ())
660 b = b->next; /* Try the next data block. */
664 /* Return TRUE if at least one more line is available for input. */
669 return (find_line (current_line + 1) == NULL) ? TRUE : FALSE;
672 /* Set the name of the input file to NAME and open it. */
675 set_input_file (const char *name)
677 if (STREQ (name, "-"))
681 input_desc = open (name, O_RDONLY);
683 error (EXIT_FAILURE, errno, "%s", name);
687 /* Write all lines from the beginning of the buffer up to, but
688 not including, line LAST_LINE, to the current output file.
689 If IGNORE is TRUE, do not output lines selected here.
690 ARGNUM is the index in ARGV of the current pattern. */
693 write_to_file (unsigned int last_line, boolean ignore, int argnum)
695 struct cstring *line;
696 unsigned int first_line; /* First available input line. */
697 unsigned int lines; /* Number of lines to output. */
700 first_line = get_first_line_in_buffer ();
702 if (first_line > last_line)
704 error (0, 0, _("%s: line number out of range"), global_argv[argnum]);
708 lines = last_line - first_line;
710 for (i = 0; i < lines; i++)
712 line = remove_line ();
715 error (0, 0, _("%s: line number out of range"), global_argv[argnum]);
719 save_line_to_file (line);
723 /* Output any lines left after all regexps have been processed. */
726 dump_rest_of_file (void)
728 struct cstring *line;
730 while ((line = remove_line ()) != NULL)
731 save_line_to_file (line);
734 /* Handle an attempt to read beyond EOF under the control of record P,
735 on iteration REPETITION if nonzero. */
738 handle_line_error (const struct control *p, int repetition)
740 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
742 fprintf (stderr, _("%s: `%s': line number out of range"),
743 program_name, umaxtostr (p->lines_required, buf));
745 fprintf (stderr, _(" on repetition %d\n"), repetition);
747 fprintf (stderr, "\n");
752 /* Determine the line number that marks the end of this file,
753 then get those lines and save them to the output file.
754 P is the control record.
755 REPETITION is the repetition number. */
758 process_line_count (const struct control *p, int repetition)
760 unsigned int linenum;
761 uintmax_t last_line_to_save = p->lines_required * (repetition + 1);
762 struct cstring *line;
764 create_output_file ();
766 linenum = get_first_line_in_buffer ();
768 while (linenum++ < last_line_to_save)
770 line = remove_line ();
772 handle_line_error (p, repetition);
773 save_line_to_file (line);
776 close_output_file ();
778 /* Ensure that the line number specified is not 1 greater than
779 the number of lines in the file. */
780 if (no_more_lines ())
781 handle_line_error (p, repetition);
785 regexp_error (struct control *p, int repetition, boolean ignore)
787 fprintf (stderr, _("%s: `%s': match not found"),
788 program_name, global_argv[p->argnum]);
791 fprintf (stderr, _(" on repetition %d\n"), repetition);
793 fprintf (stderr, "\n");
797 dump_rest_of_file ();
798 close_output_file ();
803 /* Read the input until a line matches the regexp in P, outputting
804 it unless P->IGNORE is TRUE.
805 REPETITION is this repeat-count; 0 means the first time. */
808 process_regexp (struct control *p, int repetition)
810 struct cstring *line; /* From input file. */
811 unsigned int line_len; /* To make "$" in regexps work. */
812 unsigned int break_line; /* First line number of next file. */
813 boolean ignore = p->ignore; /* If TRUE, skip this section. */
817 create_output_file ();
819 /* If there is no offset for the regular expression, or
820 it is positive, then it is not necessary to buffer the lines. */
826 line = find_line (++current_line);
829 if (p->repeat_forever)
833 dump_rest_of_file ();
834 close_output_file ();
839 regexp_error (p, repetition, ignore);
841 line_len = line->len;
842 if (line->str[line_len - 1] == '\n')
844 ret = re_search (&p->re_compiled, line->str, line_len,
845 0, line_len, (struct re_registers *) 0);
848 error (0, 0, _("error in regular expression search"));
853 line = remove_line ();
855 save_line_to_file (line);
863 /* Buffer the lines. */
866 line = find_line (++current_line);
869 if (p->repeat_forever)
873 dump_rest_of_file ();
874 close_output_file ();
879 regexp_error (p, repetition, ignore);
881 line_len = line->len;
882 if (line->str[line_len - 1] == '\n')
884 ret = re_search (&p->re_compiled, line->str, line_len,
885 0, line_len, (struct re_registers *) 0);
888 error (0, 0, _("error in regular expression search"));
896 /* Account for any offset from this regexp. */
897 break_line = current_line + p->offset;
899 write_to_file (break_line, ignore, p->argnum);
902 close_output_file ();
905 current_line = break_line;
908 /* Split the input file according to the control records we have built. */
915 for (i = 0; i < control_used; i++)
917 if (controls[i].regexpr)
919 for (j = 0; (controls[i].repeat_forever
920 || j <= controls[i].repeat); j++)
921 process_regexp (&controls[i], j);
925 for (j = 0; (controls[i].repeat_forever
926 || j <= controls[i].repeat); j++)
927 process_line_count (&controls[i], j);
931 create_output_file ();
932 dump_rest_of_file ();
933 close_output_file ();
936 /* Return the name of output file number NUM. */
939 make_filename (unsigned int num)
941 strcpy (filename_space, prefix);
943 sprintf (filename_space+strlen(prefix), suffix, num);
945 sprintf (filename_space+strlen(prefix), "%0*d", digits, num);
946 return filename_space;
949 /* Create the next output file. */
952 create_output_file (void)
954 output_filename = make_filename (files_created);
955 output_stream = fopen (output_filename, "w");
956 if (output_stream == NULL)
958 error (0, errno, "%s", output_filename);
965 /* Delete all the files we have created. */
968 delete_all_files (void)
973 for (i = 0; i < files_created; i++)
975 name = make_filename (i);
977 error (0, errno, "%s", name);
981 /* Close the current output file and print the count
982 of characters in this file. */
985 close_output_file (void)
989 if (ferror (output_stream))
991 error (0, 0, _("write error for `%s'"), output_filename);
992 output_stream = NULL;
995 if (fclose (output_stream) != 0)
997 error (0, errno, "%s", output_filename);
998 output_stream = NULL;
1001 if (bytes_written == 0 && elide_empty_files)
1003 if (unlink (output_filename))
1004 error (0, errno, "%s", output_filename);
1009 /* FIXME: if we write to stdout here, we have to close stdout
1010 and check for errors. */
1011 if (!suppress_count)
1012 fprintf (stdout, "%d\n", bytes_written);
1014 output_stream = NULL;
1018 /* Save line LINE to the output file and
1019 increment the character count for the current file. */
1022 save_line_to_file (const struct cstring *line)
1024 fwrite (line->str, sizeof (char), line->len, output_stream);
1025 bytes_written += line->len;
1028 /* Return a new, initialized control record. */
1030 static struct control *
1031 new_control_record (void)
1033 static unsigned control_allocated = 0; /* Total space allocated. */
1036 if (control_allocated == 0)
1038 control_allocated = ALLOC_SIZE;
1039 controls = (struct control *)
1040 xmalloc (sizeof (struct control) * control_allocated);
1042 else if (control_used == control_allocated)
1044 control_allocated += ALLOC_SIZE;
1045 controls = (struct control *)
1047 sizeof (struct control) * control_allocated);
1049 p = &controls[control_used++];
1052 p->repeat_forever = 0;
1053 p->lines_required = 0;
1058 /* Check if there is a numeric offset after a regular expression.
1059 STR is the entire command line argument.
1060 P is the control record for this regular expression.
1061 NUM is the numeric part of STR. */
1064 check_for_offset (struct control *p, const char *str, const char *num)
1068 if (*num != '-' && *num != '+')
1069 error (EXIT_FAILURE, 0, _("%s: `+' or `-' expected after delimeter"), str);
1071 if (xstrtoul (num + 1, NULL, 10, &val, "") != LONGINT_OK
1073 error (EXIT_FAILURE, 0, _("%s: integer expected after `%c'"), str, *num);
1074 p->offset = (unsigned int) val;
1077 p->offset = -p->offset;
1080 /* Given that the first character of command line arg STR is '{',
1081 make sure that the rest of the string is a valid repeat count
1082 and store its value in P.
1083 ARGNUM is the ARGV index of STR. */
1086 parse_repeat_count (int argnum, struct control *p, char *str)
1091 end = str + strlen (str) - 1;
1093 error (EXIT_FAILURE, 0, _("%s: `}' is required in repeat count"), str);
1096 if (str+1 == end-1 && *(str+1) == '*')
1097 p->repeat_forever = 1;
1100 if (xstrtoumax (str + 1, NULL, 10, &val, "") != LONGINT_OK)
1102 error (EXIT_FAILURE, 0,
1103 _("%s}: integer required between `{' and `}'"),
1104 global_argv[argnum]);
1112 /* Extract the regular expression from STR and check for a numeric offset.
1113 STR should start with the regexp delimiter character.
1114 Return a new control record for the regular expression.
1115 ARGNUM is the ARGV index of STR.
1116 Unless IGNORE is TRUE, mark these lines for output. */
1118 static struct control *
1119 extract_regexp (int argnum, boolean ignore, char *str)
1121 int len; /* Number of chars in this regexp. */
1123 char *closing_delim;
1127 closing_delim = strrchr (str + 1, delim);
1128 if (closing_delim == NULL)
1129 error (EXIT_FAILURE, 0,
1130 _("%s: closing delimeter `%c' missing"), str, delim);
1132 len = closing_delim - str - 1;
1133 p = new_control_record ();
1137 p->regexpr = xmalloc ((unsigned) (len + 1));
1138 strncpy (p->regexpr, str + 1, len);
1139 p->re_compiled.allocated = len * 2;
1140 p->re_compiled.buffer = xmalloc (p->re_compiled.allocated);
1141 p->re_compiled.fastmap = xmalloc (256);
1142 p->re_compiled.translate = 0;
1143 err = re_compile_pattern (p->regexpr, len, &p->re_compiled);
1146 error (0, 0, _("%s: invalid regular expression: %s"), str, err);
1150 if (closing_delim[1])
1151 check_for_offset (p, str, closing_delim + 1);
1156 /* Extract the break patterns from args START through ARGC - 1 of ARGV.
1157 After each pattern, check if the next argument is a repeat count. */
1160 parse_patterns (int argc, int start, char **argv)
1162 int i; /* Index into ARGV. */
1163 struct control *p; /* New control record created. */
1165 static uintmax_t last_val = 0;
1167 for (i = start; i < argc; i++)
1169 if (*argv[i] == '/' || *argv[i] == '%')
1171 p = extract_regexp (i, *argv[i] == '%', argv[i]);
1175 p = new_control_record ();
1178 if (xstrtoumax (argv[i], NULL, 10, &val, "") != LONGINT_OK)
1179 error (EXIT_FAILURE, 0, _("%s: invalid pattern"), argv[i]);
1181 error (EXIT_FAILURE, 0,
1182 _("%s: line number must be greater than zero"),
1186 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
1187 error (EXIT_FAILURE, 0,
1188 _("line number `%s' is smaller than preceding line number, %s"),
1189 argv[i], umaxtostr (last_val, buf));
1192 if (val == last_val)
1194 _("warning: line number `%s' is the same as preceding line number"),
1199 p->lines_required = val;
1202 if (i + 1 < argc && *argv[i + 1] == '{')
1204 /* We have a repeat count. */
1206 parse_repeat_count (i, p, argv[i]);
1212 get_format_flags (char **format_ptr)
1216 for (; **format_ptr; (*format_ptr)++)
1218 switch (**format_ptr)
1229 count += 2; /* Allow for 0x prefix preceeding an `x' conversion. */
1240 get_format_width (char **format_ptr)
1246 start = *format_ptr;
1247 for (; ISDIGIT (**format_ptr); (*format_ptr)++)
1250 ch_save = **format_ptr;
1251 **format_ptr = '\0';
1252 /* In the case where no minimum field width is explicitly specified,
1253 allow for enough octal digits to represent the value of LONG_MAX. */
1254 count = ((*format_ptr == start)
1255 ? bytes_to_octal_digits[sizeof (long)]
1256 /* FIXME: don't use atoi, it may silently overflow.
1257 Besides, we know the result is non-negative, so shouldn't
1259 : (unsigned) atoi (start));
1260 **format_ptr = ch_save;
1265 get_format_prec (char **format_ptr)
1272 if (**format_ptr != '.')
1276 if (**format_ptr == '-' || **format_ptr == '+')
1278 is_negative = (**format_ptr == '-');
1286 start = *format_ptr;
1287 for (; ISDIGIT (**format_ptr); (*format_ptr)++)
1290 /* ANSI 4.9.6.1 says that if the precision is negative, it's as good as
1293 start = *format_ptr;
1295 ch_save = **format_ptr;
1296 **format_ptr = '\0';
1297 count = (*format_ptr == start) ? 11 : atoi (start);
1298 **format_ptr = ch_save;
1304 get_format_conv_type (char **format_ptr)
1306 int ch = *((*format_ptr)++);
1319 error (EXIT_FAILURE, 0, _("missing conversion specifier in suffix"));
1324 error (EXIT_FAILURE, 0,
1325 _("invalid conversion specifier in suffix: %c"), ch);
1327 error (EXIT_FAILURE, 0,
1328 _("invalid conversion specifier in suffix: \\%.3o"), ch);
1333 max_out (char *format)
1335 unsigned out_count = 0;
1336 unsigned percents = 0;
1347 out_count += get_format_flags (&format);
1349 int width = get_format_width (&format);
1350 int prec = get_format_prec (&format);
1352 out_count += MAX (width, prec);
1354 get_format_conv_type (&format);
1359 error (EXIT_FAILURE, 0,
1360 _("missing %% conversion specification in suffix"));
1361 else if (percents > 1)
1362 error (EXIT_FAILURE, 0,
1363 _("too many %% conversion specifications in suffix"));
1369 main (int argc, char **argv)
1374 struct sigaction oldact, newact;
1377 initialize_main (&argc, &argv);
1378 program_name = argv[0];
1379 setlocale (LC_ALL, "");
1380 bindtextdomain (PACKAGE, LOCALEDIR);
1381 textdomain (PACKAGE);
1383 atexit (close_stdout);
1388 suppress_count = FALSE;
1389 remove_files = TRUE;
1390 prefix = DEFAULT_PREFIX;
1392 /* Change the way xmalloc and xrealloc fail. */
1393 xalloc_fail_func = cleanup;
1396 newact.sa_handler = interrupt_handler;
1397 sigemptyset (&newact.sa_mask);
1398 newact.sa_flags = 0;
1400 sigaction (SIGHUP, NULL, &oldact);
1401 if (oldact.sa_handler != SIG_IGN)
1402 sigaction (SIGHUP, &newact, NULL);
1404 sigaction (SIGINT, NULL, &oldact);
1405 if (oldact.sa_handler != SIG_IGN)
1406 sigaction (SIGINT, &newact, NULL);
1408 sigaction (SIGQUIT, NULL, &oldact);
1409 if (oldact.sa_handler != SIG_IGN)
1410 sigaction (SIGQUIT, &newact, NULL);
1412 sigaction (SIGTERM, NULL, &oldact);
1413 if (oldact.sa_handler != SIG_IGN)
1414 sigaction (SIGTERM, &newact, NULL);
1416 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
1417 signal (SIGHUP, interrupt_handler);
1418 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
1419 signal (SIGINT, interrupt_handler);
1420 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
1421 signal (SIGQUIT, interrupt_handler);
1422 if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
1423 signal (SIGTERM, interrupt_handler);
1426 while ((optc = getopt_long (argc, argv, "f:b:kn:sqz", longopts, NULL)) != -1)
1441 remove_files = FALSE;
1445 if (xstrtoul (optarg, NULL, 10, &val, "") != LONGINT_OK
1447 error (EXIT_FAILURE, 0, _("%s: invalid number"), optarg);
1453 suppress_count = TRUE;
1457 elide_empty_files = TRUE;
1460 case_GETOPT_HELP_CHAR;
1462 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, WRITTEN_BY);
1465 usage (EXIT_FAILURE);
1468 if (argc - optind < 2)
1470 error (0, 0, _("too few arguments"));
1471 usage (EXIT_FAILURE);
1475 filename_space = xmalloc (strlen (prefix) + max_out (suffix) + 2);
1477 filename_space = xmalloc (strlen (prefix) + digits + 2);
1479 set_input_file (argv[optind++]);
1481 parse_patterns (argc, optind, argv);
1485 if (close (input_desc) < 0)
1487 error (0, errno, _("read error"));
1491 exit (EXIT_SUCCESS);
1498 fprintf (stderr, _("Try `%s --help' for more information.\n"),
1503 Usage: %s [OPTION]... FILE PATTERN...\n\
1507 Output pieces of FILE separated by PATTERN(s) to files `xx01', `xx02', ...,\n\
1508 and output byte counts of each piece to standard output.\n\
1512 Mandatory arguments to long options are mandatory for short options too.\n\
1515 -b, --suffix-format=FORMAT use sprintf FORMAT instead of %d\n\
1516 -f, --prefix=PREFIX use PREFIX instead of `xx'\n\
1517 -k, --keep-files do not remove output files on errors\n\
1520 -n, --digits=DIGITS use specified number of digits instead of 2\n\
1521 -s, --quiet, --silent do not print counts of output file sizes\n\
1522 -z, --elide-empty-files remove empty output files\n\
1524 fputs (HELP_OPTION_DESCRIPTION, stdout);
1525 fputs (VERSION_OPTION_DESCRIPTION, stdout);
1528 Read standard input if FILE is -. Each PATTERN may be:\n\
1532 INTEGER copy up to but not including specified line number\n\
1533 /REGEXP/[OFFSET] copy up to but not including a matching line\n\
1534 %REGEXP%[OFFSET] skip to, but not including a matching line\n\
1535 {INTEGER} repeat the previous pattern specified number of times\n\
1536 {*} repeat the previous pattern as many times as possible\n\
1538 A line OFFSET is a required `+' or `-' followed by a positive integer.\n\
1540 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
1542 exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);