1 /* csplit - split a file into sections determined by context lines
2 Copyright (C) 1991 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. */
23 #include <sys/types.h>
38 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
44 static char *xrealloc ();
45 static char *xmalloc ();
46 static void cleanup ();
47 static void close_output_file ();
48 static void create_output_file ();
49 static void save_line_to_file ();
57 /* Increment size of area for control records. */
60 /* The default prefix for output file names. */
61 #define DEFAULT_PREFIX "xx"
65 /* A compiled pattern arg. */
68 char *regexpr; /* Non-compiled regular expression. */
69 struct re_pattern_buffer re_compiled; /* Compiled regular expression. */
70 int offset; /* Offset from regexp to split at. */
71 int lines_required; /* Number of lines required. */
72 int repeat; /* Repeat count. */
73 int argnum; /* ARGV index. */
74 boolean ignore; /* If true, produce no output (for regexp). */
77 /* Initial size of data area in buffers. */
78 #define START_SIZE 8191
80 /* Increment size for data area. */
81 #define INCR_SIZE 2048
83 /* Number of lines kept in each node in line list. */
87 /* Some small values to test the algorithms. */
88 #define START_SIZE 200
93 /* A string with a length count. */
100 /* Pointers to the beginnings of lines in the buffer area.
101 These structures are linked together if needed. */
104 unsigned used; /* Number of offsets used in this struct. */
105 unsigned insert_index; /* Next offset to use when inserting line. */
106 unsigned retrieve_index; /* Next index to use when retrieving line. */
107 struct cstring starts[CTRL_SIZE]; /* Lines in the data area. */
108 struct line *next; /* Next in linked list. */
111 /* The structure to hold the input lines.
112 Contains a pointer to the data area and a list containing
113 pointers to the individual lines. */
116 unsigned bytes_alloc; /* Size of the buffer area. */
117 unsigned bytes_used; /* Bytes used in the buffer area. */
118 unsigned start_line; /* First line number in this buffer. */
119 unsigned first_available; /* First line that can be retrieved. */
120 unsigned num_lines; /* Number of complete lines in this buffer. */
121 char *buffer; /* Data area. */
122 struct line *line_start; /* Head of list of pointers to lines. */
123 struct line *curr_line; /* The line start record currently in use. */
124 struct buffer_record *next;
127 /* The name this program was run with. */
130 /* Convert the number of 8-bit bytes of a binary representation to
131 the number of characters required to represent the same quantity
132 as an unsigned octal. For example, a 32-bit (4-byte) quantity may
133 require a field width as wide as 11 characters. */
134 static const unsigned int bytes_to_octal_digits[] =
135 {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};
137 /* Input file descriptor. */
138 static int input_desc = 0;
140 /* List of available buffers. */
141 static struct buffer_record *free_list = NULL;
143 /* Start of buffer list. */
144 static struct buffer_record *head = NULL;
146 /* Partially read line. */
147 static char *hold_area = NULL;
149 /* Number of chars in `hold_area'. */
150 static unsigned hold_count = 0;
152 /* Number of the last line in the buffers. */
153 static unsigned last_line_number = 0;
155 /* Number of the line currently being examined. */
156 static unsigned current_line = 0;
158 /* Number of the last line in the input file. */
159 static unsigned last_line_in_file = 0;
161 /* If TRUE, we have read EOF. */
162 static boolean have_read_eof = FALSE;
164 /* Name of output files. */
165 static char *filename_space = NULL;
167 /* Prefix part of output file names. */
168 static char *prefix = NULL;
170 /* Suffix part of output file names. */
171 static char *suffix = NULL;
173 /* Number of digits to use in output file names. */
174 static int digits = 2;
176 /* Number of files created so far. */
177 static unsigned files_created = 0;
179 /* Number of bytes written to current file. */
180 static unsigned bytes_written;
182 /* Output file pointer. */
183 static FILE *output_stream = NULL;
185 /* Output file name. */
186 static char *output_filename = NULL;
188 /* Perhaps it would be cleaner to pass arg values instead of indexes. */
189 static char **global_argv;
191 /* If TRUE, do not print the count of bytes in each output file. */
192 static boolean suppress_count;
194 /* If TRUE, remove output files on error. */
195 static boolean remove_files;
197 /* If TRUE, remove all output files which have a zero length. */
198 static boolean abandon_null_files;
200 /* The compiled pattern arguments, which determine how to split
202 static struct control *controls;
204 /* Number of elements in `controls'. */
205 static unsigned control_used;
207 /* If non-zero, display usage information and exit. */
208 static int show_help;
210 /* If non-zero, print the version on standard output then exit. */
211 static int show_version;
213 static struct option const longopts[] =
215 {"digits", required_argument, NULL, 'n'},
216 {"quiet", no_argument, NULL, 'q'},
217 {"silent", no_argument, NULL, 's'},
218 {"keep-files", no_argument, NULL, 'k'},
219 {"abandon-null-files", no_argument, NULL, 'z'},
220 {"prefix", required_argument, NULL, 'f'},
221 {"suffix", required_argument, NULL, 'b'},
222 {"help", no_argument, &show_help, 1},
223 {"version", no_argument, &show_version, 1},
227 /* Allocate N bytes of memory dynamically, with error checking. */
238 error (0, 0, "virtual memory exhausted");
244 /* Change the size of an allocated block of memory P to N bytes,
246 If P is NULL, run xmalloc.
247 If N is 0, run free and return NULL. */
264 error (0, 0, "virtual memory exhausted");
270 /* Keep track of NUM chars of a partial line in buffer START.
271 These chars will be retrieved later when another large buffer is read.
272 It is not necessary to create a new buffer for these chars; instead,
273 we keep a pointer to the existing buffer. This buffer *is* on the
274 free list, and when the next buffer is obtained from this list
275 (even if it is this one), these chars will be placed at the
276 start of the new buffer. */
279 save_to_hold_area (start, num)
287 /* Read up to MAX chars from the input stream into DEST.
288 Return the number of chars read. */
291 read_input (dest, max)
300 bytes_read = read (input_desc, dest, max);
303 have_read_eof = TRUE;
307 error (0, errno, "read error");
314 /* Initialize existing line record P. */
317 clear_line_control (p)
322 p->retrieve_index = 0;
325 /* Initialize all line records in B. */
328 clear_all_line_control (b)
329 struct buffer_record *b;
333 for (l = b->line_start; l; l = l->next)
334 clear_line_control (l);
337 /* Return a new, initialized line record. */
344 p = (struct line *) xmalloc (sizeof (struct line));
347 clear_line_control (p);
352 /* Record LINE_START, which is the address of the start of a line
353 of length LINE_LEN in the large buffer, in the lines buffer of B. */
356 keep_new_line (b, line_start, line_len)
357 struct buffer_record *b;
363 /* If there is no existing area to keep line info, get some. */
364 if (b->line_start == NULL)
365 b->line_start = b->curr_line = new_line_control ();
367 /* If existing area for lines is full, get more. */
368 if (b->curr_line->used == CTRL_SIZE)
370 b->curr_line->next = new_line_control ();
371 b->curr_line = b->curr_line->next;
376 /* Record the start of the line, and update counters. */
377 l->starts[l->insert_index].str = line_start;
378 l->starts[l->insert_index].len = line_len;
383 /* Scan the buffer in B for newline characters
384 and record the line start locations and lengths in B.
385 Return the number of lines found in this buffer.
387 There may be an incomplete line at the end of the buffer;
388 a pointer is kept to this area, which will be used when
389 the next buffer is filled. */
392 record_line_starts (b)
393 struct buffer_record *b;
395 char *line_start; /* Start of current line. */
396 char *line_end; /* End of each line found. */
397 unsigned bytes_left; /* Length of incomplete last line. */
398 unsigned lines; /* Number of lines found. */
399 unsigned line_length; /* Length of each line found. */
401 if (b->bytes_used == 0)
405 line_start = b->buffer;
406 bytes_left = b->bytes_used;
410 line_end = memchr (line_start, '\n', bytes_left);
411 if (line_end == NULL)
413 line_length = line_end - line_start + 1;
414 keep_new_line (b, line_start, line_length);
415 bytes_left -= line_length;
416 line_start = line_end + 1;
420 /* Check for an incomplete last line. */
425 keep_new_line (b, line_start, bytes_left);
427 last_line_in_file = last_line_number + lines;
430 save_to_hold_area (line_start, bytes_left);
433 b->num_lines = lines;
434 b->first_available = b->start_line = last_line_number + 1;
435 last_line_number += lines;
440 /* Return a new buffer with room to store SIZE bytes, plus
441 an extra byte for safety. */
443 static struct buffer_record *
444 create_new_buffer (size)
447 struct buffer_record *new_buffer;
449 new_buffer = (struct buffer_record *)
450 xmalloc (sizeof (struct buffer_record));
452 new_buffer->buffer = (char *) xmalloc (size + 1);
454 new_buffer->bytes_alloc = size;
455 new_buffer->line_start = new_buffer->curr_line = NULL;
460 /* Return a new buffer of at least MINSIZE bytes. If a buffer of at
461 least that size is currently free, use it, otherwise create a new one. */
463 static struct buffer_record *
464 get_new_buffer (min_size)
467 struct buffer_record *p, *q;
468 struct buffer_record *new_buffer; /* Buffer to return. */
469 unsigned alloc_size; /* Actual size that will be requested. */
471 alloc_size = START_SIZE;
472 while (min_size > alloc_size)
473 alloc_size += INCR_SIZE;
475 if (free_list == NULL)
476 new_buffer = create_new_buffer (alloc_size);
479 /* Use first-fit to find a buffer. */
480 p = new_buffer = NULL;
485 if (q->bytes_alloc >= min_size)
498 new_buffer = (q ? q : create_new_buffer (alloc_size));
500 new_buffer->curr_line = new_buffer->line_start;
501 clear_all_line_control (new_buffer);
504 new_buffer->num_lines = 0;
505 new_buffer->bytes_used = 0;
506 new_buffer->start_line = new_buffer->first_available = last_line_number + 1;
507 new_buffer->next = NULL;
512 /* Add buffer BUF to the list of free buffers. */
516 struct buffer_record *buf;
518 buf->next = free_list;
522 /* Append buffer BUF to the linked list of buffers that contain
523 some data yet to be processed. */
527 struct buffer_record *buf;
529 struct buffer_record *p;
532 buf->curr_line = buf->line_start;
538 for (p = head; p->next; p = p->next)
544 /* Fill a buffer of input.
546 Set the initial size of the buffer to a default.
547 Fill the buffer (from the hold area and input stream)
548 and find the individual lines.
549 If no lines are found (the buffer is too small to hold the next line),
550 release the current buffer (whose contents would have been put in the
551 hold area) and repeat the process with another large buffer until at least
552 one entire line has been read.
554 Return TRUE if a new buffer was obtained, otherwise false
555 (in which case end-of-file must have been encountered). */
560 struct buffer_record *b;
561 unsigned bytes_wanted = START_SIZE; /* Minimum buffer size. */
562 unsigned bytes_avail; /* Size of new buffer created. */
563 unsigned lines_found; /* Number of lines in this new buffer. */
564 char *p; /* Place to load into buffer. */
569 /* We must make the buffer at least as large as the amount of data
570 in the partial line left over from the last call. */
571 if (bytes_wanted < hold_count)
572 bytes_wanted = hold_count;
576 b = get_new_buffer (bytes_wanted);
577 bytes_avail = b->bytes_alloc; /* Size of buffer returned. */
580 /* First check the `holding' area for a partial line. */
584 bcopy (hold_area, p, hold_count);
586 b->bytes_used += hold_count;
587 bytes_avail -= hold_count;
591 b->bytes_used += (unsigned) read_input (p, bytes_avail);
593 lines_found = record_line_starts (b);
594 bytes_wanted = b->bytes_alloc + INCR_SIZE;
598 while (!lines_found && !have_read_eof);
603 return lines_found != 0;
606 /* Return the line number of the first line that has not yet been retrieved. */
609 get_first_line_in_buffer ()
611 if (head == NULL && !load_buffer ())
612 error (1, errno, "input disappeared");
614 return head->first_available;
617 /* Return a pointer to the logical first line in the buffer and make the
618 next line the logical first line.
619 Return NULL if there is no more input. */
621 static struct cstring *
624 struct cstring *line; /* Return value. */
625 struct line *l; /* For convenience. */
627 if (head == NULL && !load_buffer ())
630 if (current_line < head->first_available)
631 current_line = head->first_available;
633 ++(head->first_available);
637 line = &l->starts[l->retrieve_index];
639 /* Advance index to next line. */
640 if (++l->retrieve_index == l->used)
642 /* Go on to the next line record. */
643 head->curr_line = l->next;
644 if (head->curr_line == NULL || head->curr_line->used == 0)
646 /* Go on to the next data block. */
647 struct buffer_record *b = head;
656 /* Search the buffers for line LINENUM, reading more input if necessary.
657 Return a pointer to the line, or NULL if it is not found in the file. */
659 static struct cstring *
663 struct buffer_record *b;
665 if (head == NULL && !load_buffer ())
668 if (linenum < head->start_line)
673 if (linenum < b->start_line + b->num_lines)
675 /* The line is in this buffer. */
677 unsigned offset; /* How far into the buffer the line is. */
680 offset = linenum - b->start_line;
681 /* Find the control record. */
682 while (offset >= CTRL_SIZE)
687 return &l->starts[offset];
689 if (b->next == NULL && !load_buffer ())
691 b = b->next; /* Try the next data block. */
695 /* Return TRUE if at least one more line is available for input. */
700 return (find_line (current_line + 1) == NULL) ? TRUE : FALSE;
703 /* Set the name of the input file to NAME and open it. */
706 set_input_file (name)
709 if (!strcmp (name, "-"))
713 input_desc = open (name, O_RDONLY);
715 error (1, errno, "%s", name);
719 /* Write all lines from the beginning of the buffer up to, but
720 not including, line LAST_LINE, to the current output file.
721 If IGNORE is TRUE, do not output lines selected here.
722 ARGNUM is the index in ARGV of the current pattern. */
725 write_to_file (last_line, ignore, argnum)
730 struct cstring *line;
731 unsigned first_line; /* First available input line. */
732 unsigned lines; /* Number of lines to output. */
735 first_line = get_first_line_in_buffer ();
737 if (first_line > last_line)
739 error (0, 0, "%s: line number out of range", global_argv[argnum]);
743 lines = last_line - first_line;
745 for (i = 0; i < lines; i++)
747 line = remove_line ();
750 error (0, 0, "%s: line number out of range", global_argv[argnum]);
754 save_line_to_file (line);
758 /* Output any lines left after all regexps have been processed. */
763 struct cstring *line;
765 while ((line = remove_line ()) != NULL)
766 save_line_to_file (line);
769 /* Handle an attempt to read beyond EOF under the control of record P,
770 on iteration REPETITION if nonzero. */
773 handle_line_error (p, repetition)
777 fprintf (stderr, "%s: `%d': line number out of range",
778 program_name, p->lines_required);
780 fprintf (stderr, " on repetition %d\n", repetition);
782 fprintf (stderr, "\n");
787 /* Determine the line number that marks the end of this file,
788 then get those lines and save them to the output file.
789 P is the control record.
790 REPETITION is the repetition number. */
793 process_line_count (p, repetition)
798 unsigned last_line_to_save = p->lines_required * (repetition + 1);
799 struct cstring *line;
801 create_output_file ();
803 linenum = get_first_line_in_buffer ();
805 /* Check for requesting a line that has already been written out.
806 If this ever happens, it's due to a bug in csplit. */
807 if (linenum >= last_line_to_save)
808 handle_line_error (p, repetition);
810 while (linenum++ < last_line_to_save)
812 line = remove_line ();
814 handle_line_error (p, repetition);
815 save_line_to_file (line);
818 close_output_file ();
820 /* Ensure that the line number specified is not 1 greater than
821 the number of lines in the file. */
822 if (no_more_lines ())
823 handle_line_error (p, repetition);
827 regexp_error (p, repetition, ignore)
832 fprintf (stderr, "%s: `%s': match not found",
833 program_name, global_argv[p->argnum]);
836 fprintf (stderr, " on repetition %d\n", repetition);
838 fprintf (stderr, "\n");
842 dump_rest_of_file ();
843 close_output_file ();
848 /* Read the input until a line matches the regexp in P, outputting
849 it unless P->IGNORE is TRUE.
850 REPETITION is this repeat-count; 0 means the first time. */
853 process_regexp (p, repetition)
857 struct cstring *line; /* From input file. */
858 unsigned line_len; /* To make "$" in regexps work. */
859 unsigned break_line; /* First line number of next file. */
860 boolean ignore = p->ignore; /* If TRUE, skip this section. */
864 create_output_file ();
866 /* If there is no offset for the regular expression, or
867 it is positive, then it is not necessary to buffer the lines. */
873 line = find_line (++current_line);
876 if (p->repeat == INT_MAX)
880 dump_rest_of_file ();
881 close_output_file ();
886 regexp_error (p, repetition, ignore);
888 line_len = line->len;
889 if (line->str[line_len - 1] == '\n')
891 ret = re_search (&p->re_compiled, line->str, line_len,
892 0, line_len, (struct re_registers *) 0);
895 error (0, 0, "error in regular expression search");
900 line = remove_line ();
902 save_line_to_file (line);
910 /* Buffer the lines. */
913 line = find_line (++current_line);
916 if (p->repeat == INT_MAX)
920 dump_rest_of_file ();
921 close_output_file ();
926 regexp_error (p, repetition, ignore);
928 line_len = line->len;
929 if (line->str[line_len - 1] == '\n')
931 ret = re_search (&p->re_compiled, line->str, line_len,
932 0, line_len, (struct re_registers *) 0);
935 error (0, 0, "error in regular expression search");
943 /* Account for any offset from this regexp. */
944 break_line = current_line + p->offset;
946 write_to_file (break_line, ignore, p->argnum);
949 close_output_file ();
951 current_line = break_line;
954 /* Split the input file according to the control records we have built. */
961 for (i = 0; i < control_used; i++)
963 if (controls[i].regexpr)
965 for (j = 0; j <= controls[i].repeat; j++)
966 process_regexp (&controls[i], j);
970 for (j = 0; j <= controls[i].repeat; j++)
971 process_line_count (&controls[i], j);
975 create_output_file ();
976 dump_rest_of_file ();
977 close_output_file ();
980 /* Return the name of output file number NUM. */
986 strcpy (filename_space, prefix);
988 sprintf (filename_space+strlen(prefix), suffix, num);
990 sprintf (filename_space+strlen(prefix), "%0*d", digits, num);
991 return filename_space;
994 /* Create the next output file. */
997 create_output_file ()
999 output_filename = make_filename (files_created);
1000 output_stream = fopen (output_filename, "w");
1001 if (output_stream == NULL)
1003 error (0, errno, "%s", output_filename);
1010 /* Delete all the files we have created. */
1018 for (i = 0; i < files_created; i++)
1020 name = make_filename (i);
1022 error (0, errno, "%s", name);
1026 /* Close the current output file and print the count
1027 of characters in this file. */
1030 close_output_file ()
1034 if (fclose (output_stream) == EOF)
1036 error (0, errno, "write error for `%s'", output_filename);
1039 if (bytes_written == 0 && abandon_null_files)
1041 if (unlink (output_filename))
1042 error (0, errno, "%s", output_filename);
1046 if (!suppress_count)
1047 fprintf (stdout, "%d\n", bytes_written);
1048 output_stream = NULL;
1052 /* Optionally remove files created so far; then exit.
1053 Called when an error detected. */
1059 close_output_file ();
1062 delete_all_files ();
1067 /* Save line LINE to the output file and
1068 increment the character count for the current file. */
1071 save_line_to_file (line)
1072 struct cstring *line;
1074 fwrite (line->str, sizeof (char), line->len, output_stream);
1075 bytes_written += line->len;
1078 /* Return a new, initialized control record. */
1080 static struct control *
1081 new_control_record ()
1083 static unsigned control_allocated = 0; /* Total space allocated. */
1086 if (control_allocated == 0)
1088 control_allocated = ALLOC_SIZE;
1089 controls = (struct control *)
1090 xmalloc (sizeof (struct control) * control_allocated);
1092 else if (control_used == control_allocated)
1094 control_allocated += ALLOC_SIZE;
1095 controls = (struct control *)
1096 xrealloc (controls, sizeof (struct control) * control_allocated);
1098 p = &controls[control_used++];
1101 p->lines_required = 0;
1106 /* Convert string NUM to an integer and put the value in *RESULT.
1107 Return a TRUE if the string consists entirely of digits,
1111 string_to_number (result, num)
1121 while ((ch = *num++))
1125 val = val * 10 + ch - '0';
1132 /* Check if there is a numeric offset after a regular expression.
1133 STR is the entire command line argument.
1134 P is the control record for this regular expression.
1135 NUM is the numeric part of STR. */
1138 check_for_offset (p, str, num)
1143 if (*num != '-' && *num != '+')
1144 error (1, 0, "%s: `+' or `-' expected after delimeter", str);
1146 if (!string_to_number (&p->offset, num + 1))
1147 error (1, 0, "%s: integer expected after `%c'", str, *num);
1150 p->offset = -p->offset;
1153 /* Given that the first character of command line arg STR is '{',
1154 make sure that the rest of the string is a valid repeat count
1155 and store its value in P.
1156 ARGNUM is the ARGV index of STR. */
1159 parse_repeat_count (argnum, p, str)
1166 end = str + strlen (str) - 1;
1168 error (1, 0, "%s: `}' is required in repeat count", str);
1171 if (str+1 == end-1 && *(str+1) == '*')
1172 p->repeat = INT_MAX;
1174 if (!string_to_number (&p->repeat, str + 1))
1175 error (1, 0, "%s}: integer required between `{' and `}'",
1176 global_argv[argnum]);
1181 /* Extract the regular expression from STR and check for a numeric offset.
1182 STR should start with the regexp delimiter character.
1183 Return a new control record for the regular expression.
1184 ARGNUM is the ARGV index of STR.
1185 Unless IGNORE is TRUE, mark these lines for output. */
1187 static struct control *
1188 extract_regexp (argnum, ignore, str)
1193 int len; /* Number of chars in this regexp. */
1195 char *closing_delim;
1199 closing_delim = rindex (str + 1, delim);
1200 if (closing_delim == NULL)
1201 error (1, 0, "%s: closing delimeter `%c' missing", str, delim);
1203 len = closing_delim - str - 1;
1204 p = new_control_record ();
1208 p->regexpr = (char *) xmalloc ((unsigned) (len + 1));
1209 strncpy (p->regexpr, str + 1, len);
1210 p->re_compiled.allocated = len * 2;
1211 p->re_compiled.buffer = (unsigned char *) xmalloc (p->re_compiled.allocated);
1212 p->re_compiled.fastmap = xmalloc (256);
1213 p->re_compiled.translate = 0;
1214 err = re_compile_pattern (p->regexpr, len, &p->re_compiled);
1217 error (0, 0, "%s: invalid regular expression: %s", str, err);
1221 if (closing_delim[1])
1222 check_for_offset (p, str, closing_delim + 1);
1227 /* Extract the break patterns from args START through ARGC - 1 of ARGV.
1228 After each pattern, check if the next argument is a repeat count. */
1231 parse_patterns (argc, start, argv)
1236 int i; /* Index into ARGV. */
1237 struct control *p; /* New control record created. */
1239 for (i = start; i < argc; i++)
1241 if (*argv[i] == '/' || *argv[i] == '%')
1243 p = extract_regexp (i, *argv[i] == '%', argv[i]);
1247 p = new_control_record ();
1249 if (!string_to_number (&p->lines_required, argv[i]))
1250 error (1, 0, "%s: invalid pattern", argv[i]);
1253 if (i + 1 < argc && *argv[i + 1] == '{')
1255 /* We have a repeat count. */
1257 parse_repeat_count (i, p, argv[i]);
1263 get_format_flags (format_ptr)
1268 for (; **format_ptr; (*format_ptr)++)
1270 switch (**format_ptr)
1281 count += 2; /* Allow for 0x prefix preceeding an `x' conversion. */
1292 get_format_width (format_ptr)
1299 start = *format_ptr;
1300 for (; **format_ptr; (*format_ptr)++)
1301 if (**format_ptr < '0' || **format_ptr > '9')
1304 ch_save = **format_ptr;
1305 **format_ptr = '\0';
1306 /* In the case where no minimum field width is explicitly specified,
1307 allow for enough octal digits to represent the value of LONG_MAX. */
1308 count = ((*format_ptr == start)
1309 ? bytes_to_octal_digits[sizeof (long)]
1311 **format_ptr = ch_save;
1316 get_format_prec (format_ptr)
1324 if (**format_ptr != '.')
1328 if (**format_ptr == '-' || **format_ptr == '+')
1330 is_negative = (**format_ptr == '-');
1338 start = *format_ptr;
1339 for (; **format_ptr; (*format_ptr)++)
1340 if (**format_ptr < '0' || **format_ptr > '9')
1343 /* ANSI 4.9.6.1 says that if the precision is negative, it's as good as
1346 start = *format_ptr;
1348 ch_save = **format_ptr;
1349 **format_ptr = '\0';
1350 count = (*format_ptr == start) ? 11 : atoi (start);
1351 **format_ptr = ch_save;
1357 get_format_conv_type (format_ptr)
1360 int ch = *((*format_ptr)++);
1373 error (1, 0, "missing conversion specifier in suffix");
1378 error (1, 0, "invalid conversion specifier in suffix: %c", ch);
1380 error (1, 0, "invalid conversion specifier in suffix: \\%.3o", ch);
1388 unsigned out_count = 0;
1389 unsigned percents = 0;
1400 out_count += get_format_flags (&format);
1402 int width = get_format_width (&format);
1403 int prec = get_format_prec (&format);
1405 out_count += MAX (width, prec);
1407 get_format_conv_type (&format);
1412 error (1, 0, "missing %% conversion specification in suffix");
1413 else if (percents > 1)
1414 error (1, 0, "too many %% conversion specifications in suffix");
1420 interrupt_handler ()
1422 error (0, 0, "interrupted");
1432 #ifdef _POSIX_VERSION
1433 struct sigaction oldact, newact;
1434 #endif /* _POSIX_VERSION */
1436 program_name = argv[0];
1440 suppress_count = FALSE;
1441 remove_files = TRUE;
1442 prefix = DEFAULT_PREFIX;
1444 #ifdef _POSIX_VERSION
1445 newact.sa_handler = interrupt_handler;
1446 sigemptyset (&newact.sa_mask);
1447 newact.sa_flags = 0;
1449 sigaction (SIGHUP, NULL, &oldact);
1450 if (oldact.sa_handler != SIG_IGN)
1451 sigaction (SIGHUP, &newact, NULL);
1453 sigaction (SIGINT, NULL, &oldact);
1454 if (oldact.sa_handler != SIG_IGN)
1455 sigaction (SIGINT, &newact, NULL);
1457 sigaction (SIGQUIT, NULL, &oldact);
1458 if (oldact.sa_handler != SIG_IGN)
1459 sigaction (SIGQUIT, &newact, NULL);
1461 sigaction (SIGTERM, NULL, &oldact);
1462 if (oldact.sa_handler != SIG_IGN)
1463 sigaction (SIGTERM, &newact, NULL);
1464 #else /* !_POSIX_VERSION */
1465 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
1466 signal (SIGHUP, interrupt_handler);
1467 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
1468 signal (SIGINT, interrupt_handler);
1469 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
1470 signal (SIGQUIT, interrupt_handler);
1471 if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
1472 signal (SIGTERM, interrupt_handler);
1475 while ((optc = getopt_long (argc, argv, "f:b:kn:sqz", longopts, (int *) 0))
1491 remove_files = FALSE;
1495 if (!string_to_number (&digits, optarg))
1496 error (1, 0, "%s: invalid number", optarg);
1501 suppress_count = TRUE;
1505 abandon_null_files = TRUE;
1514 printf ("%s\n", version_string);
1521 if (optind >= argc - 1)
1525 filename_space = (char *) xmalloc (strlen (prefix) + max_out (suffix) + 2);
1527 filename_space = (char *) xmalloc (strlen (prefix) + digits + 2);
1529 set_input_file (argv[optind++]);
1531 parse_patterns (argc, optind, argv);
1535 if (close (input_desc) < 0)
1537 error (0, errno, "read error");
1548 Usage: %s [-sqkz] [-f prefix] [-b suffix] [-n digits] [--prefix=prefix]\n\
1549 [--suffix=suffix] [--digits=digits] [--quiet] [--silent]\n\
1550 [--keep-files] [--abandon-null-files] [--help] [--version]\n\