1 /* csplit - split a file into sections determined by context lines
2 Copyright (C) 1991, 1995 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
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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>
29 #endif /* HAVE_LIMITS_H */
43 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
48 static char *xrealloc ();
49 static char *xmalloc ();
50 static void cleanup ();
51 static void close_output_file ();
52 static void create_output_file ();
53 static void save_line_to_file ();
61 /* Increment size of area for control records. */
64 /* The default prefix for output file names. */
65 #define DEFAULT_PREFIX "xx"
69 /* A compiled pattern arg. */
72 char *regexpr; /* Non-compiled regular expression. */
73 struct re_pattern_buffer re_compiled; /* Compiled regular expression. */
74 int offset; /* Offset from regexp to split at. */
75 int lines_required; /* Number of lines required. */
76 int repeat; /* Repeat count. */
77 int repeat_forever; /* Non-zero if `*' used as a repeat count. */
78 int argnum; /* ARGV index. */
79 boolean ignore; /* If true, produce no output (for regexp). */
82 /* Initial size of data area in buffers. */
83 #define START_SIZE 8191
85 /* Increment size for data area. */
86 #define INCR_SIZE 2048
88 /* Number of lines kept in each node in line list. */
92 /* Some small values to test the algorithms. */
93 #define START_SIZE 200
98 /* A string with a length count. */
105 /* Pointers to the beginnings of lines in the buffer area.
106 These structures are linked together if needed. */
109 unsigned used; /* Number of offsets used in this struct. */
110 unsigned insert_index; /* Next offset to use when inserting line. */
111 unsigned retrieve_index; /* Next index to use when retrieving line. */
112 struct cstring starts[CTRL_SIZE]; /* Lines in the data area. */
113 struct line *next; /* Next in linked list. */
116 /* The structure to hold the input lines.
117 Contains a pointer to the data area and a list containing
118 pointers to the individual lines. */
121 unsigned bytes_alloc; /* Size of the buffer area. */
122 unsigned bytes_used; /* Bytes used in the buffer area. */
123 unsigned start_line; /* First line number in this buffer. */
124 unsigned first_available; /* First line that can be retrieved. */
125 unsigned num_lines; /* Number of complete lines in this buffer. */
126 char *buffer; /* Data area. */
127 struct line *line_start; /* Head of list of pointers to lines. */
128 struct line *curr_line; /* The line start record currently in use. */
129 struct buffer_record *next;
132 /* The name this program was run with. */
135 /* Convert the number of 8-bit bytes of a binary representation to
136 the number of characters required to represent the same quantity
137 as an unsigned octal. For example, a 32-bit (4-byte) quantity may
138 require a field width as wide as 11 characters. */
139 static const unsigned int bytes_to_octal_digits[] =
140 {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};
142 /* Input file descriptor. */
143 static int input_desc = 0;
145 /* List of available buffers. */
146 static struct buffer_record *free_list = NULL;
148 /* Start of buffer list. */
149 static struct buffer_record *head = NULL;
151 /* Partially read line. */
152 static char *hold_area = NULL;
154 /* Number of chars in `hold_area'. */
155 static unsigned hold_count = 0;
157 /* Number of the last line in the buffers. */
158 static unsigned last_line_number = 0;
160 /* Number of the line currently being examined. */
161 static unsigned current_line = 0;
163 /* Number of the last line in the input file. */
164 static unsigned last_line_in_file = 0;
166 /* If TRUE, we have read EOF. */
167 static boolean have_read_eof = FALSE;
169 /* Name of output files. */
170 static char *filename_space = NULL;
172 /* Prefix part of output file names. */
173 static char *prefix = NULL;
175 /* Suffix part of output file names. */
176 static char *suffix = NULL;
178 /* Number of digits to use in output file names. */
179 static int digits = 2;
181 /* Number of files created so far. */
182 static unsigned int files_created = 0;
184 /* Number of bytes written to current file. */
185 static unsigned int bytes_written;
187 /* Output file pointer. */
188 static FILE *output_stream = NULL;
190 /* Output file name. */
191 static char *output_filename = NULL;
193 /* Perhaps it would be cleaner to pass arg values instead of indexes. */
194 static char **global_argv;
196 /* If TRUE, do not print the count of bytes in each output file. */
197 static boolean suppress_count;
199 /* If TRUE, remove output files on error. */
200 static boolean remove_files;
202 /* If TRUE, remove all output files which have a zero length. */
203 static boolean elide_empty_files;
205 /* The compiled pattern arguments, which determine how to split
207 static struct control *controls;
209 /* Number of elements in `controls'. */
210 static unsigned int control_used;
212 /* If non-zero, display usage information and exit. */
213 static int show_help;
215 /* If non-zero, print the version on standard output then exit. */
216 static int show_version;
218 static struct option const longopts[] =
220 {"digits", required_argument, NULL, 'n'},
221 {"quiet", no_argument, NULL, 'q'},
222 {"silent", no_argument, NULL, 's'},
223 {"keep-files", no_argument, NULL, 'k'},
224 {"elide-empty-files", no_argument, NULL, 'z'},
225 {"prefix", required_argument, NULL, 'f'},
226 {"suffix-format", required_argument, NULL, 'b'},
227 {"help", no_argument, &show_help, 1},
228 {"version", no_argument, &show_version, 1},
232 /* Allocate N bytes of memory dynamically, with error checking. */
243 error (0, 0, "virtual memory exhausted");
249 /* Change the size of an allocated block of memory P to N bytes,
251 If P is NULL, run xmalloc.
252 If N is 0, run free and return NULL. */
269 error (0, 0, "virtual memory exhausted");
275 /* Keep track of NUM chars of a partial line in buffer START.
276 These chars will be retrieved later when another large buffer is read.
277 It is not necessary to create a new buffer for these chars; instead,
278 we keep a pointer to the existing buffer. This buffer *is* on the
279 free list, and when the next buffer is obtained from this list
280 (even if it is this one), these chars will be placed at the
281 start of the new buffer. */
284 save_to_hold_area (start, num)
292 /* Read up to MAX chars from the input stream into DEST.
293 Return the number of chars read. */
296 read_input (dest, max)
305 bytes_read = safe_read (input_desc, dest, max);
308 have_read_eof = TRUE;
312 error (0, errno, "read error");
319 /* Initialize existing line record P. */
322 clear_line_control (p)
327 p->retrieve_index = 0;
330 /* Initialize all line records in B. */
333 clear_all_line_control (b)
334 struct buffer_record *b;
338 for (l = b->line_start; l; l = l->next)
339 clear_line_control (l);
342 /* Return a new, initialized line record. */
349 p = (struct line *) xmalloc (sizeof (struct line));
352 clear_line_control (p);
357 /* Record LINE_START, which is the address of the start of a line
358 of length LINE_LEN in the large buffer, in the lines buffer of B. */
361 keep_new_line (b, line_start, line_len)
362 struct buffer_record *b;
368 /* If there is no existing area to keep line info, get some. */
369 if (b->line_start == NULL)
370 b->line_start = b->curr_line = new_line_control ();
372 /* If existing area for lines is full, get more. */
373 if (b->curr_line->used == CTRL_SIZE)
375 b->curr_line->next = new_line_control ();
376 b->curr_line = b->curr_line->next;
381 /* Record the start of the line, and update counters. */
382 l->starts[l->insert_index].str = line_start;
383 l->starts[l->insert_index].len = line_len;
388 /* Scan the buffer in B for newline characters
389 and record the line start locations and lengths in B.
390 Return the number of lines found in this buffer.
392 There may be an incomplete line at the end of the buffer;
393 a pointer is kept to this area, which will be used when
394 the next buffer is filled. */
397 record_line_starts (b)
398 struct buffer_record *b;
400 char *line_start; /* Start of current line. */
401 char *line_end; /* End of each line found. */
402 unsigned int bytes_left; /* Length of incomplete last line. */
403 unsigned int lines; /* Number of lines found. */
404 unsigned int line_length; /* Length of each line found. */
406 if (b->bytes_used == 0)
410 line_start = b->buffer;
411 bytes_left = b->bytes_used;
415 line_end = memchr (line_start, '\n', bytes_left);
416 if (line_end == NULL)
418 line_length = line_end - line_start + 1;
419 keep_new_line (b, line_start, line_length);
420 bytes_left -= line_length;
421 line_start = line_end + 1;
425 /* Check for an incomplete last line. */
430 keep_new_line (b, line_start, bytes_left);
432 last_line_in_file = last_line_number + lines;
435 save_to_hold_area (line_start, bytes_left);
438 b->num_lines = lines;
439 b->first_available = b->start_line = last_line_number + 1;
440 last_line_number += lines;
445 /* Return a new buffer with room to store SIZE bytes, plus
446 an extra byte for safety. */
448 static struct buffer_record *
449 create_new_buffer (size)
452 struct buffer_record *new_buffer;
454 new_buffer = (struct buffer_record *)
455 xmalloc (sizeof (struct buffer_record));
457 new_buffer->buffer = (char *) xmalloc (size + 1);
459 new_buffer->bytes_alloc = size;
460 new_buffer->line_start = new_buffer->curr_line = NULL;
465 /* Return a new buffer of at least MINSIZE bytes. If a buffer of at
466 least that size is currently free, use it, otherwise create a new one. */
468 static struct buffer_record *
469 get_new_buffer (min_size)
470 unsigned int min_size;
472 struct buffer_record *p, *q;
473 struct buffer_record *new_buffer; /* Buffer to return. */
474 unsigned int alloc_size; /* Actual size that will be requested. */
476 alloc_size = START_SIZE;
477 while (min_size > alloc_size)
478 alloc_size += INCR_SIZE;
480 if (free_list == NULL)
481 new_buffer = create_new_buffer (alloc_size);
484 /* Use first-fit to find a buffer. */
485 p = new_buffer = NULL;
490 if (q->bytes_alloc >= min_size)
503 new_buffer = (q ? q : create_new_buffer (alloc_size));
505 new_buffer->curr_line = new_buffer->line_start;
506 clear_all_line_control (new_buffer);
509 new_buffer->num_lines = 0;
510 new_buffer->bytes_used = 0;
511 new_buffer->start_line = new_buffer->first_available = last_line_number + 1;
512 new_buffer->next = NULL;
517 /* Add buffer BUF to the list of free buffers. */
521 struct buffer_record *buf;
523 buf->next = free_list;
527 /* Append buffer BUF to the linked list of buffers that contain
528 some data yet to be processed. */
532 struct buffer_record *buf;
534 struct buffer_record *p;
537 buf->curr_line = buf->line_start;
543 for (p = head; p->next; p = p->next)
549 /* Fill a buffer of input.
551 Set the initial size of the buffer to a default.
552 Fill the buffer (from the hold area and input stream)
553 and find the individual lines.
554 If no lines are found (the buffer is too small to hold the next line),
555 release the current buffer (whose contents would have been put in the
556 hold area) and repeat the process with another large buffer until at least
557 one entire line has been read.
559 Return TRUE if a new buffer was obtained, otherwise false
560 (in which case end-of-file must have been encountered). */
565 struct buffer_record *b;
566 unsigned int bytes_wanted = START_SIZE; /* Minimum buffer size. */
567 unsigned int bytes_avail; /* Size of new buffer created. */
568 unsigned int lines_found; /* Number of lines in this new buffer. */
569 char *p; /* Place to load into buffer. */
574 /* We must make the buffer at least as large as the amount of data
575 in the partial line left over from the last call. */
576 if (bytes_wanted < hold_count)
577 bytes_wanted = hold_count;
581 b = get_new_buffer (bytes_wanted);
582 bytes_avail = b->bytes_alloc; /* Size of buffer returned. */
585 /* First check the `holding' area for a partial line. */
589 memcpy (p, hold_area, hold_count);
591 b->bytes_used += hold_count;
592 bytes_avail -= hold_count;
596 b->bytes_used += (unsigned int) read_input (p, bytes_avail);
598 lines_found = record_line_starts (b);
599 bytes_wanted = b->bytes_alloc * 2;
603 while (!lines_found && !have_read_eof);
608 return lines_found != 0;
611 /* Return the line number of the first line that has not yet been retrieved. */
614 get_first_line_in_buffer ()
616 if (head == NULL && !load_buffer ())
617 error (1, errno, "input disappeared");
619 return head->first_available;
622 /* Return a pointer to the logical first line in the buffer and make the
623 next line the logical first line.
624 Return NULL if there is no more input. */
626 static struct cstring *
629 struct cstring *line; /* Return value. */
630 struct line *l; /* For convenience. */
632 if (head == NULL && !load_buffer ())
635 if (current_line < head->first_available)
636 current_line = head->first_available;
638 ++(head->first_available);
642 line = &l->starts[l->retrieve_index];
644 /* Advance index to next line. */
645 if (++l->retrieve_index == l->used)
647 /* Go on to the next line record. */
648 head->curr_line = l->next;
649 if (head->curr_line == NULL || head->curr_line->used == 0)
651 /* Go on to the next data block. */
652 struct buffer_record *b = head;
661 /* Search the buffers for line LINENUM, reading more input if necessary.
662 Return a pointer to the line, or NULL if it is not found in the file. */
664 static struct cstring *
666 unsigned int linenum;
668 struct buffer_record *b;
670 if (head == NULL && !load_buffer ())
673 if (linenum < head->start_line)
678 if (linenum < b->start_line + b->num_lines)
680 /* The line is in this buffer. */
682 unsigned int offset; /* How far into the buffer the line is. */
685 offset = linenum - b->start_line;
686 /* Find the control record. */
687 while (offset >= CTRL_SIZE)
692 return &l->starts[offset];
694 if (b->next == NULL && !load_buffer ())
696 b = b->next; /* Try the next data block. */
700 /* Return TRUE if at least one more line is available for input. */
705 return (find_line (current_line + 1) == NULL) ? TRUE : FALSE;
708 /* Set the name of the input file to NAME and open it. */
711 set_input_file (name)
714 if (!strcmp (name, "-"))
718 input_desc = open (name, O_RDONLY);
720 error (1, errno, "%s", name);
724 /* Write all lines from the beginning of the buffer up to, but
725 not including, line LAST_LINE, to the current output file.
726 If IGNORE is TRUE, do not output lines selected here.
727 ARGNUM is the index in ARGV of the current pattern. */
730 write_to_file (last_line, ignore, argnum)
731 unsigned int last_line;
735 struct cstring *line;
736 unsigned int first_line; /* First available input line. */
737 unsigned int lines; /* Number of lines to output. */
740 first_line = get_first_line_in_buffer ();
742 if (first_line > last_line)
744 error (0, 0, "%s: line number out of range", global_argv[argnum]);
748 lines = last_line - first_line;
750 for (i = 0; i < lines; i++)
752 line = remove_line ();
755 error (0, 0, "%s: line number out of range", global_argv[argnum]);
759 save_line_to_file (line);
763 /* Output any lines left after all regexps have been processed. */
768 struct cstring *line;
770 while ((line = remove_line ()) != NULL)
771 save_line_to_file (line);
774 /* Handle an attempt to read beyond EOF under the control of record P,
775 on iteration REPETITION if nonzero. */
778 handle_line_error (p, repetition)
782 fprintf (stderr, "%s: `%d': line number out of range",
783 program_name, p->lines_required);
785 fprintf (stderr, " on repetition %d\n", repetition);
787 fprintf (stderr, "\n");
792 /* Determine the line number that marks the end of this file,
793 then get those lines and save them to the output file.
794 P is the control record.
795 REPETITION is the repetition number. */
798 process_line_count (p, repetition)
802 unsigned int linenum;
803 unsigned int last_line_to_save = p->lines_required * (repetition + 1);
804 struct cstring *line;
806 create_output_file ();
808 linenum = get_first_line_in_buffer ();
810 /* Check for requesting a line that has already been written out.
811 If this ever happens, it's due to a bug in csplit. */
812 if (linenum >= last_line_to_save)
815 while (linenum++ < last_line_to_save)
817 line = remove_line ();
819 handle_line_error (p, repetition);
820 save_line_to_file (line);
823 close_output_file ();
825 /* Ensure that the line number specified is not 1 greater than
826 the number of lines in the file. */
827 if (no_more_lines ())
828 handle_line_error (p, repetition);
832 regexp_error (p, repetition, ignore)
837 fprintf (stderr, "%s: `%s': match not found",
838 program_name, global_argv[p->argnum]);
841 fprintf (stderr, " on repetition %d\n", repetition);
843 fprintf (stderr, "\n");
847 dump_rest_of_file ();
848 close_output_file ();
853 /* Read the input until a line matches the regexp in P, outputting
854 it unless P->IGNORE is TRUE.
855 REPETITION is this repeat-count; 0 means the first time. */
858 process_regexp (p, repetition)
862 struct cstring *line; /* From input file. */
863 unsigned int line_len; /* To make "$" in regexps work. */
864 unsigned int break_line; /* First line number of next file. */
865 boolean ignore = p->ignore; /* If TRUE, skip this section. */
869 create_output_file ();
871 /* If there is no offset for the regular expression, or
872 it is positive, then it is not necessary to buffer the lines. */
878 line = find_line (++current_line);
881 if (p->repeat_forever)
885 dump_rest_of_file ();
886 close_output_file ();
891 regexp_error (p, repetition, ignore);
893 line_len = line->len;
894 if (line->str[line_len - 1] == '\n')
896 ret = re_search (&p->re_compiled, line->str, line_len,
897 0, line_len, (struct re_registers *) 0);
900 error (0, 0, "error in regular expression search");
905 line = remove_line ();
907 save_line_to_file (line);
915 /* Buffer the lines. */
918 line = find_line (++current_line);
921 if (p->repeat_forever)
925 dump_rest_of_file ();
926 close_output_file ();
931 regexp_error (p, repetition, ignore);
933 line_len = line->len;
934 if (line->str[line_len - 1] == '\n')
936 ret = re_search (&p->re_compiled, line->str, line_len,
937 0, line_len, (struct re_registers *) 0);
940 error (0, 0, "error in regular expression search");
948 /* Account for any offset from this regexp. */
949 break_line = current_line + p->offset;
951 write_to_file (break_line, ignore, p->argnum);
954 close_output_file ();
956 current_line = break_line;
959 /* Split the input file according to the control records we have built. */
966 for (i = 0; i < control_used; i++)
968 if (controls[i].regexpr)
970 for (j = 0; (controls[i].repeat_forever
971 || j <= controls[i].repeat); j++)
972 process_regexp (&controls[i], j);
976 for (j = 0; (controls[i].repeat_forever
977 || j <= controls[i].repeat); j++)
978 process_line_count (&controls[i], j);
982 create_output_file ();
983 dump_rest_of_file ();
984 close_output_file ();
987 /* Return the name of output file number NUM. */
993 strcpy (filename_space, prefix);
995 sprintf (filename_space+strlen(prefix), suffix, num);
997 sprintf (filename_space+strlen(prefix), "%0*d", digits, num);
998 return filename_space;
1001 /* Create the next output file. */
1004 create_output_file ()
1006 output_filename = make_filename (files_created);
1007 output_stream = fopen (output_filename, "w");
1008 if (output_stream == NULL)
1010 error (0, errno, "%s", output_filename);
1017 /* Delete all the files we have created. */
1025 for (i = 0; i < files_created; i++)
1027 name = make_filename (i);
1029 error (0, errno, "%s", name);
1033 /* Close the current output file and print the count
1034 of characters in this file. */
1037 close_output_file ()
1041 if (fclose (output_stream) == EOF)
1043 error (0, errno, "write error for `%s'", output_filename);
1046 if (bytes_written == 0 && elide_empty_files)
1048 if (unlink (output_filename))
1049 error (0, errno, "%s", output_filename);
1053 if (!suppress_count)
1054 fprintf (stdout, "%d\n", bytes_written);
1055 output_stream = NULL;
1059 /* Optionally remove files created so far; then exit.
1060 Called when an error detected. */
1066 close_output_file ();
1069 delete_all_files ();
1074 /* Save line LINE to the output file and
1075 increment the character count for the current file. */
1078 save_line_to_file (line)
1079 struct cstring *line;
1081 fwrite (line->str, sizeof (char), line->len, output_stream);
1082 bytes_written += line->len;
1085 /* Return a new, initialized control record. */
1087 static struct control *
1088 new_control_record ()
1090 static unsigned control_allocated = 0; /* Total space allocated. */
1093 if (control_allocated == 0)
1095 control_allocated = ALLOC_SIZE;
1096 controls = (struct control *)
1097 xmalloc (sizeof (struct control) * control_allocated);
1099 else if (control_used == control_allocated)
1101 control_allocated += ALLOC_SIZE;
1102 controls = (struct control *)
1103 xrealloc (controls, sizeof (struct control) * control_allocated);
1105 p = &controls[control_used++];
1108 p->repeat_forever = 0;
1109 p->lines_required = 0;
1114 /* Convert string NUM to an integer and put the value in *RESULT.
1115 Return a TRUE if the string consists entirely of digits,
1117 /* FIXME: use xstrtoul in place of this function. */
1120 string_to_number (result, num)
1130 while ((ch = *num++))
1134 val = val * 10 + ch - '0';
1141 /* Check if there is a numeric offset after a regular expression.
1142 STR is the entire command line argument.
1143 P is the control record for this regular expression.
1144 NUM is the numeric part of STR. */
1147 check_for_offset (p, str, num)
1152 if (*num != '-' && *num != '+')
1153 error (1, 0, "%s: `+' or `-' expected after delimeter", str);
1155 if (!string_to_number (&p->offset, num + 1))
1156 error (1, 0, "%s: integer expected after `%c'", str, *num);
1159 p->offset = -p->offset;
1162 /* Given that the first character of command line arg STR is '{',
1163 make sure that the rest of the string is a valid repeat count
1164 and store its value in P.
1165 ARGNUM is the ARGV index of STR. */
1168 parse_repeat_count (argnum, p, str)
1175 end = str + strlen (str) - 1;
1177 error (1, 0, "%s: `}' is required in repeat count", str);
1180 if (str+1 == end-1 && *(str+1) == '*')
1181 p->repeat_forever = 1;
1183 if (!string_to_number (&p->repeat, str + 1))
1184 error (1, 0, "%s}: integer required between `{' and `}'",
1185 global_argv[argnum]);
1190 /* Extract the regular expression from STR and check for a numeric offset.
1191 STR should start with the regexp delimiter character.
1192 Return a new control record for the regular expression.
1193 ARGNUM is the ARGV index of STR.
1194 Unless IGNORE is TRUE, mark these lines for output. */
1196 static struct control *
1197 extract_regexp (argnum, ignore, str)
1202 int len; /* Number of chars in this regexp. */
1204 char *closing_delim;
1208 closing_delim = strrchr (str + 1, delim);
1209 if (closing_delim == NULL)
1210 error (1, 0, "%s: closing delimeter `%c' missing", str, delim);
1212 len = closing_delim - str - 1;
1213 p = new_control_record ();
1217 p->regexpr = (char *) xmalloc ((unsigned) (len + 1));
1218 strncpy (p->regexpr, str + 1, len);
1219 p->re_compiled.allocated = len * 2;
1220 p->re_compiled.buffer = (unsigned char *) xmalloc (p->re_compiled.allocated);
1221 p->re_compiled.fastmap = xmalloc (256);
1222 p->re_compiled.translate = 0;
1223 err = re_compile_pattern (p->regexpr, len, &p->re_compiled);
1226 error (0, 0, "%s: invalid regular expression: %s", str, err);
1230 if (closing_delim[1])
1231 check_for_offset (p, str, closing_delim + 1);
1236 /* Extract the break patterns from args START through ARGC - 1 of ARGV.
1237 After each pattern, check if the next argument is a repeat count. */
1240 parse_patterns (argc, start, argv)
1245 int i; /* Index into ARGV. */
1246 struct control *p; /* New control record created. */
1248 for (i = start; i < argc; i++)
1250 if (*argv[i] == '/' || *argv[i] == '%')
1252 p = extract_regexp (i, *argv[i] == '%', argv[i]);
1256 p = new_control_record ();
1258 if (!string_to_number (&p->lines_required, argv[i]))
1259 error (1, 0, "%s: invalid pattern", argv[i]);
1262 if (i + 1 < argc && *argv[i + 1] == '{')
1264 /* We have a repeat count. */
1266 parse_repeat_count (i, p, argv[i]);
1272 get_format_flags (format_ptr)
1277 for (; **format_ptr; (*format_ptr)++)
1279 switch (**format_ptr)
1290 count += 2; /* Allow for 0x prefix preceeding an `x' conversion. */
1301 get_format_width (format_ptr)
1308 start = *format_ptr;
1309 for (; **format_ptr; (*format_ptr)++)
1310 if (!ISDIGIT (**format_ptr))
1313 ch_save = **format_ptr;
1314 **format_ptr = '\0';
1315 /* In the case where no minimum field width is explicitly specified,
1316 allow for enough octal digits to represent the value of LONG_MAX. */
1317 count = ((*format_ptr == start)
1318 ? bytes_to_octal_digits[sizeof (long)]
1320 **format_ptr = ch_save;
1325 get_format_prec (format_ptr)
1333 if (**format_ptr != '.')
1337 if (**format_ptr == '-' || **format_ptr == '+')
1339 is_negative = (**format_ptr == '-');
1347 start = *format_ptr;
1348 for (; **format_ptr; (*format_ptr)++)
1349 if (!ISDIGIT (**format_ptr))
1352 /* ANSI 4.9.6.1 says that if the precision is negative, it's as good as
1355 start = *format_ptr;
1357 ch_save = **format_ptr;
1358 **format_ptr = '\0';
1359 count = (*format_ptr == start) ? 11 : atoi (start);
1360 **format_ptr = ch_save;
1366 get_format_conv_type (format_ptr)
1369 int ch = *((*format_ptr)++);
1382 error (1, 0, "missing conversion specifier in suffix");
1387 error (1, 0, "invalid conversion specifier in suffix: %c", ch);
1389 error (1, 0, "invalid conversion specifier in suffix: \\%.3o", ch);
1397 unsigned out_count = 0;
1398 unsigned percents = 0;
1409 out_count += get_format_flags (&format);
1411 int width = get_format_width (&format);
1412 int prec = get_format_prec (&format);
1414 out_count += MAX (width, prec);
1416 get_format_conv_type (&format);
1421 error (1, 0, "missing %% conversion specification in suffix");
1422 else if (percents > 1)
1423 error (1, 0, "too many %% conversion specifications in suffix");
1429 interrupt_handler ()
1431 error (0, 0, "interrupted");
1441 #ifdef _POSIX_VERSION
1442 struct sigaction oldact, newact;
1443 #endif /* _POSIX_VERSION */
1445 program_name = argv[0];
1449 suppress_count = FALSE;
1450 remove_files = TRUE;
1451 prefix = DEFAULT_PREFIX;
1453 #ifdef _POSIX_VERSION
1454 newact.sa_handler = interrupt_handler;
1455 sigemptyset (&newact.sa_mask);
1456 newact.sa_flags = 0;
1458 sigaction (SIGHUP, NULL, &oldact);
1459 if (oldact.sa_handler != SIG_IGN)
1460 sigaction (SIGHUP, &newact, NULL);
1462 sigaction (SIGINT, NULL, &oldact);
1463 if (oldact.sa_handler != SIG_IGN)
1464 sigaction (SIGINT, &newact, NULL);
1466 sigaction (SIGQUIT, NULL, &oldact);
1467 if (oldact.sa_handler != SIG_IGN)
1468 sigaction (SIGQUIT, &newact, NULL);
1470 sigaction (SIGTERM, NULL, &oldact);
1471 if (oldact.sa_handler != SIG_IGN)
1472 sigaction (SIGTERM, &newact, NULL);
1473 #else /* !_POSIX_VERSION */
1474 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
1475 signal (SIGHUP, interrupt_handler);
1476 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
1477 signal (SIGINT, interrupt_handler);
1478 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
1479 signal (SIGQUIT, interrupt_handler);
1480 if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
1481 signal (SIGTERM, interrupt_handler);
1484 while ((optc = getopt_long (argc, argv, "f:b:kn:sqz", longopts, (int *) 0))
1500 remove_files = FALSE;
1504 if (!string_to_number (&digits, optarg))
1505 error (1, 0, "%s: invalid number", optarg);
1510 suppress_count = TRUE;
1514 elide_empty_files = TRUE;
1523 printf ("csplit - %s\n", version_string);
1530 if (optind >= argc - 1)
1534 filename_space = (char *) xmalloc (strlen (prefix) + max_out (suffix) + 2);
1536 filename_space = (char *) xmalloc (strlen (prefix) + digits + 2);
1538 set_input_file (argv[optind++]);
1540 parse_patterns (argc, optind, argv);
1544 if (close (input_desc) < 0)
1546 error (0, errno, "read error");
1558 fprintf (stderr, "Try `%s --help' for more information.\n",
1563 Usage: %s [OPTION]... FILE PATTERN...\n\
1567 Output pieces of FILE separated by PATTERN(s) to files `xx01', `xx02', ...,\n\
1568 and output byte counts of each piece to standard output.\n\
1570 -b, --suffix-format=FORMAT use sprintf FORMAT instead of %%d\n\
1571 -f, --prefix=PREFIX use PREFIX instead of `xx'\n\
1572 -k, --keep-files do not remove output files on errors\n\
1573 -n, --digits=DIGITS use specified number of digits instead of 2\n\
1574 -s, --quiet, --silent do not print counts of output file sizes\n\
1575 -z, --elide-empty-files remove empty output files\n\
1576 --help display this help and exit\n\
1577 --version output version information and exit\n\
1579 Read standard input if FILE is -. Each PATTERN may be:\n\
1581 INTEGER copy up to but not including specified line number\n\
1582 /REGEXP/[OFFSET] copy up to but not including a matching line\n\
1583 %%REGEXP%%[OFFSET] skip to, but not including a matching line\n\
1584 {INTEGER} repeat the previous pattern specified number of times\n\
1585 {*} repeat the previous pattern as many times as possible\n\
1587 A line OFFSET is a required `+' or `-' followed by a positive integer.\n\