Line data Source code
1 : /* csplit - split a file into sections determined by context lines
2 : Copyright (C) 91, 1995-2007 Free Software Foundation, Inc.
3 :
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 3 of the License, or
7 : (at your option) any later version.
8 :
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.
13 :
14 : You should have received a copy of the GNU General Public License
15 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
16 :
17 : /* Written by Stuart Kemp, cpsrk@groper.jcu.edu.au.
18 : Modified by David MacKenzie, djm@gnu.ai.mit.edu. */
19 :
20 : #include <config.h>
21 :
22 : #include <getopt.h>
23 : #include <sys/types.h>
24 : #include <signal.h>
25 :
26 : #include "system.h"
27 :
28 : #include <regex.h>
29 :
30 : #include "error.h"
31 : #include "fd-reopen.h"
32 : #include "inttostr.h"
33 : #include "quote.h"
34 : #include "safe-read.h"
35 : #include "stdio--.h"
36 : #include "xstrtol.h"
37 :
38 : /* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is
39 : present. */
40 : #ifndef SA_NOCLDSTOP
41 : # define SA_NOCLDSTOP 0
42 : # define sigprocmask(How, Set, Oset) /* empty */
43 : # define sigset_t int
44 : # if ! HAVE_SIGINTERRUPT
45 : # define siginterrupt(sig, flag) /* empty */
46 : # endif
47 : #endif
48 :
49 : /* The official name of this program (e.g., no `g' prefix). */
50 : #define PROGRAM_NAME "csplit"
51 :
52 : #define AUTHORS "Stuart Kemp", "David MacKenzie"
53 :
54 : /* Increment size of area for control records. */
55 : #define ALLOC_SIZE 20
56 :
57 : /* The default prefix for output file names. */
58 : #define DEFAULT_PREFIX "xx"
59 :
60 : /* A compiled pattern arg. */
61 : struct control
62 : {
63 : intmax_t offset; /* Offset from regexp to split at. */
64 : uintmax_t lines_required; /* Number of lines required. */
65 : uintmax_t repeat; /* Repeat count. */
66 : int argnum; /* ARGV index. */
67 : bool repeat_forever; /* True if `*' used as a repeat count. */
68 : bool ignore; /* If true, produce no output (for regexp). */
69 : bool regexpr; /* True if regular expression was used. */
70 : struct re_pattern_buffer re_compiled; /* Compiled regular expression. */
71 : };
72 :
73 : /* Initial size of data area in buffers. */
74 : #define START_SIZE 8191
75 :
76 : /* Increment size for data area. */
77 : #define INCR_SIZE 2048
78 :
79 : /* Number of lines kept in each node in line list. */
80 : #define CTRL_SIZE 80
81 :
82 : #ifdef DEBUG
83 : /* Some small values to test the algorithms. */
84 : # define START_SIZE 200
85 : # define INCR_SIZE 10
86 : # define CTRL_SIZE 1
87 : #endif
88 :
89 : /* A string with a length count. */
90 : struct cstring
91 : {
92 : size_t len;
93 : char *str;
94 : };
95 :
96 : /* Pointers to the beginnings of lines in the buffer area.
97 : These structures are linked together if needed. */
98 : struct line
99 : {
100 : size_t used; /* Number of offsets used in this struct. */
101 : size_t insert_index; /* Next offset to use when inserting line. */
102 : size_t retrieve_index; /* Next index to use when retrieving line. */
103 : struct cstring starts[CTRL_SIZE]; /* Lines in the data area. */
104 : struct line *next; /* Next in linked list. */
105 : };
106 :
107 : /* The structure to hold the input lines.
108 : Contains a pointer to the data area and a list containing
109 : pointers to the individual lines. */
110 : struct buffer_record
111 : {
112 : size_t bytes_alloc; /* Size of the buffer area. */
113 : size_t bytes_used; /* Bytes used in the buffer area. */
114 : uintmax_t start_line; /* First line number in this buffer. */
115 : uintmax_t first_available; /* First line that can be retrieved. */
116 : size_t num_lines; /* Number of complete lines in this buffer. */
117 : char *buffer; /* Data area. */
118 : struct line *line_start; /* Head of list of pointers to lines. */
119 : struct line *curr_line; /* The line start record currently in use. */
120 : struct buffer_record *next;
121 : };
122 :
123 : static void close_output_file (void);
124 : static void create_output_file (void);
125 : static void delete_all_files (bool);
126 : static void save_line_to_file (const struct cstring *line);
127 : void usage (int status);
128 :
129 : /* The name this program was run with. */
130 : char *program_name;
131 :
132 : /* Start of buffer list. */
133 : static struct buffer_record *head = NULL;
134 :
135 : /* Partially read line. */
136 : static char *hold_area = NULL;
137 :
138 : /* Number of bytes in `hold_area'. */
139 : static size_t hold_count = 0;
140 :
141 : /* Number of the last line in the buffers. */
142 : static uintmax_t last_line_number = 0;
143 :
144 : /* Number of the line currently being examined. */
145 : static uintmax_t current_line = 0;
146 :
147 : /* If true, we have read EOF. */
148 : static bool have_read_eof = false;
149 :
150 : /* Name of output files. */
151 : static char *volatile filename_space = NULL;
152 :
153 : /* Prefix part of output file names. */
154 : static char const *volatile prefix = NULL;
155 :
156 : /* Suffix part of output file names. */
157 : static char *volatile suffix = NULL;
158 :
159 : /* Number of digits to use in output file names. */
160 : static int volatile digits = 2;
161 :
162 : /* Number of files created so far. */
163 : static unsigned int volatile files_created = 0;
164 :
165 : /* Number of bytes written to current file. */
166 : static uintmax_t bytes_written;
167 :
168 : /* Output file pointer. */
169 : static FILE *output_stream = NULL;
170 :
171 : /* Output file name. */
172 : static char *output_filename = NULL;
173 :
174 : /* Perhaps it would be cleaner to pass arg values instead of indexes. */
175 : static char **global_argv;
176 :
177 : /* If true, do not print the count of bytes in each output file. */
178 : static bool suppress_count;
179 :
180 : /* If true, remove output files on error. */
181 : static bool volatile remove_files;
182 :
183 : /* If true, remove all output files which have a zero length. */
184 : static bool elide_empty_files;
185 :
186 : /* The compiled pattern arguments, which determine how to split
187 : the input file. */
188 : static struct control *controls;
189 :
190 : /* Number of elements in `controls'. */
191 : static size_t control_used;
192 :
193 : /* The set of signals that are caught. */
194 : static sigset_t caught_signals;
195 :
196 : static struct option const longopts[] =
197 : {
198 : {"digits", required_argument, NULL, 'n'},
199 : {"quiet", no_argument, NULL, 'q'},
200 : {"silent", no_argument, NULL, 's'},
201 : {"keep-files", no_argument, NULL, 'k'},
202 : {"elide-empty-files", no_argument, NULL, 'z'},
203 : {"prefix", required_argument, NULL, 'f'},
204 : {"suffix-format", required_argument, NULL, 'b'},
205 : {GETOPT_HELP_OPTION_DECL},
206 : {GETOPT_VERSION_OPTION_DECL},
207 : {NULL, 0, NULL, 0}
208 : };
209 :
210 : /* Optionally remove files created so far; then exit.
211 : Called when an error detected. */
212 :
213 : static void
214 6 : cleanup (void)
215 : {
216 : sigset_t oldset;
217 :
218 6 : close_output_file ();
219 :
220 6 : sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
221 6 : delete_all_files (false);
222 6 : sigprocmask (SIG_SETMASK, &oldset, NULL);
223 6 : }
224 :
225 : static void cleanup_fatal (void) ATTRIBUTE_NORETURN;
226 : static void
227 6 : cleanup_fatal (void)
228 : {
229 6 : cleanup ();
230 6 : exit (EXIT_FAILURE);
231 : }
232 :
233 : extern void
234 0 : xalloc_die (void)
235 : {
236 0 : error (0, 0, "%s", _("memory exhausted"));
237 0 : cleanup_fatal ();
238 : }
239 :
240 : static void
241 0 : interrupt_handler (int sig)
242 : {
243 : if (! SA_NOCLDSTOP)
244 : signal (sig, SIG_IGN);
245 :
246 0 : delete_all_files (true);
247 :
248 0 : signal (sig, SIG_DFL);
249 0 : raise (sig);
250 0 : }
251 :
252 : /* Keep track of NUM bytes of a partial line in buffer START.
253 : These bytes will be retrieved later when another large buffer is read. */
254 :
255 : static void
256 5 : save_to_hold_area (char *start, size_t num)
257 : {
258 5 : free (hold_area);
259 5 : hold_area = start;
260 5 : hold_count = num;
261 5 : }
262 :
263 : /* Read up to MAX_N_BYTES bytes from the input stream into DEST.
264 : Return the number of bytes read. */
265 :
266 : static size_t
267 45 : read_input (char *dest, size_t max_n_bytes)
268 : {
269 : size_t bytes_read;
270 :
271 45 : if (max_n_bytes == 0)
272 0 : return 0;
273 :
274 45 : bytes_read = safe_read (STDIN_FILENO, dest, max_n_bytes);
275 :
276 45 : if (bytes_read == 0)
277 21 : have_read_eof = true;
278 :
279 45 : if (bytes_read == SAFE_READ_ERROR)
280 : {
281 3 : error (0, errno, _("read error"));
282 3 : cleanup_fatal ();
283 : }
284 :
285 42 : return bytes_read;
286 : }
287 :
288 : /* Initialize existing line record P. */
289 :
290 : static void
291 24 : clear_line_control (struct line *p)
292 : {
293 24 : p->used = 0;
294 24 : p->insert_index = 0;
295 24 : p->retrieve_index = 0;
296 24 : }
297 :
298 : /* Return a new, initialized line record. */
299 :
300 : static struct line *
301 24 : new_line_control (void)
302 : {
303 24 : struct line *p = xmalloc (sizeof *p);
304 :
305 24 : p->next = NULL;
306 24 : clear_line_control (p);
307 :
308 24 : return p;
309 : }
310 :
311 : /* Record LINE_START, which is the address of the start of a line
312 : of length LINE_LEN in the large buffer, in the lines buffer of B. */
313 :
314 : static void
315 133 : keep_new_line (struct buffer_record *b, char *line_start, size_t line_len)
316 : {
317 : struct line *l;
318 :
319 : /* If there is no existing area to keep line info, get some. */
320 133 : if (b->line_start == NULL)
321 24 : b->line_start = b->curr_line = new_line_control ();
322 :
323 : /* If existing area for lines is full, get more. */
324 133 : if (b->curr_line->used == CTRL_SIZE)
325 : {
326 0 : b->curr_line->next = new_line_control ();
327 0 : b->curr_line = b->curr_line->next;
328 : }
329 :
330 133 : l = b->curr_line;
331 :
332 : /* Record the start of the line, and update counters. */
333 133 : l->starts[l->insert_index].str = line_start;
334 133 : l->starts[l->insert_index].len = line_len;
335 133 : l->used++;
336 133 : l->insert_index++;
337 133 : }
338 :
339 : /* Scan the buffer in B for newline characters
340 : and record the line start locations and lengths in B.
341 : Return the number of lines found in this buffer.
342 :
343 : There may be an incomplete line at the end of the buffer;
344 : a pointer is kept to this area, which will be used when
345 : the next buffer is filled. */
346 :
347 : static size_t
348 42 : record_line_starts (struct buffer_record *b)
349 : {
350 : char *line_start; /* Start of current line. */
351 : char *line_end; /* End of each line found. */
352 : size_t bytes_left; /* Length of incomplete last line. */
353 : size_t lines; /* Number of lines found. */
354 : size_t line_length; /* Length of each line found. */
355 :
356 42 : if (b->bytes_used == 0)
357 16 : return 0;
358 :
359 26 : lines = 0;
360 26 : line_start = b->buffer;
361 26 : bytes_left = b->bytes_used;
362 :
363 : for (;;)
364 : {
365 282 : line_end = memchr (line_start, '\n', bytes_left);
366 154 : if (line_end == NULL)
367 26 : break;
368 128 : line_length = line_end - line_start + 1;
369 128 : keep_new_line (b, line_start, line_length);
370 128 : bytes_left -= line_length;
371 128 : line_start = line_end + 1;
372 128 : lines++;
373 : }
374 :
375 : /* Check for an incomplete last line. */
376 26 : if (bytes_left)
377 : {
378 10 : if (have_read_eof)
379 : {
380 5 : keep_new_line (b, line_start, bytes_left);
381 5 : lines++;
382 : }
383 : else
384 5 : save_to_hold_area (xmemdup (line_start, bytes_left), bytes_left);
385 : }
386 :
387 26 : b->num_lines = lines;
388 26 : b->first_available = b->start_line = last_line_number + 1;
389 26 : last_line_number += lines;
390 :
391 26 : return lines;
392 : }
393 :
394 : /* Return a new buffer with room to store SIZE bytes, plus
395 : an extra byte for safety. */
396 :
397 : static struct buffer_record *
398 45 : create_new_buffer (size_t size)
399 : {
400 45 : struct buffer_record *new_buffer = xmalloc (sizeof *new_buffer);
401 :
402 45 : new_buffer->buffer = xmalloc (size + 1);
403 :
404 45 : new_buffer->bytes_alloc = size;
405 45 : new_buffer->line_start = new_buffer->curr_line = NULL;
406 :
407 45 : return new_buffer;
408 : }
409 :
410 : /* Return a new buffer of at least MINSIZE bytes. If a buffer of at
411 : least that size is currently free, use it, otherwise create a new one. */
412 :
413 : static struct buffer_record *
414 45 : get_new_buffer (size_t min_size)
415 : {
416 : struct buffer_record *new_buffer; /* Buffer to return. */
417 : size_t alloc_size; /* Actual size that will be requested. */
418 :
419 45 : alloc_size = START_SIZE;
420 45 : if (alloc_size < min_size)
421 : {
422 2 : size_t s = min_size - alloc_size + INCR_SIZE - 1;
423 2 : alloc_size += s - s % INCR_SIZE;
424 : }
425 :
426 45 : new_buffer = create_new_buffer (alloc_size);
427 :
428 45 : new_buffer->num_lines = 0;
429 45 : new_buffer->bytes_used = 0;
430 45 : new_buffer->start_line = new_buffer->first_available = last_line_number + 1;
431 45 : new_buffer->next = NULL;
432 :
433 45 : return new_buffer;
434 : }
435 :
436 : static void
437 43 : free_buffer (struct buffer_record *buf)
438 : {
439 43 : free (buf->buffer);
440 43 : buf->buffer = NULL;
441 43 : }
442 :
443 : /* Append buffer BUF to the linked list of buffers that contain
444 : some data yet to be processed. */
445 :
446 : static void
447 24 : save_buffer (struct buffer_record *buf)
448 : {
449 : struct buffer_record *p;
450 :
451 24 : buf->next = NULL;
452 24 : buf->curr_line = buf->line_start;
453 :
454 24 : if (head == NULL)
455 23 : head = buf;
456 : else
457 : {
458 1 : for (p = head; p->next; p = p->next)
459 : /* Do nothing. */ ;
460 1 : p->next = buf;
461 : }
462 24 : }
463 :
464 : /* Fill a buffer of input.
465 :
466 : Set the initial size of the buffer to a default.
467 : Fill the buffer (from the hold area and input stream)
468 : and find the individual lines.
469 : If no lines are found (the buffer is too small to hold the next line),
470 : release the current buffer (whose contents would have been put in the
471 : hold area) and repeat the process with another large buffer until at least
472 : one entire line has been read.
473 :
474 : Return true if a new buffer was obtained, otherwise false
475 : (in which case end-of-file must have been encountered). */
476 :
477 : static bool
478 50 : load_buffer (void)
479 : {
480 : struct buffer_record *b;
481 50 : size_t bytes_wanted = START_SIZE; /* Minimum buffer size. */
482 : size_t bytes_avail; /* Size of new buffer created. */
483 : size_t lines_found; /* Number of lines in this new buffer. */
484 : char *p; /* Place to load into buffer. */
485 :
486 50 : if (have_read_eof)
487 7 : return false;
488 :
489 : /* We must make the buffer at least as large as the amount of data
490 : in the partial line left over from the last call. */
491 43 : if (bytes_wanted < hold_count)
492 0 : bytes_wanted = hold_count;
493 :
494 : while (1)
495 : {
496 47 : b = get_new_buffer (bytes_wanted);
497 45 : bytes_avail = b->bytes_alloc; /* Size of buffer returned. */
498 45 : p = b->buffer;
499 :
500 : /* First check the `holding' area for a partial line. */
501 45 : if (hold_count)
502 : {
503 5 : memcpy (p, hold_area, hold_count);
504 5 : p += hold_count;
505 5 : b->bytes_used += hold_count;
506 5 : bytes_avail -= hold_count;
507 5 : hold_count = 0;
508 : }
509 :
510 45 : b->bytes_used += read_input (p, bytes_avail);
511 :
512 42 : lines_found = record_line_starts (b);
513 42 : if (!lines_found)
514 18 : free_buffer (b);
515 :
516 42 : if (lines_found || have_read_eof)
517 : break;
518 :
519 2 : if (xalloc_oversized (2, b->bytes_alloc))
520 0 : xalloc_die ();
521 2 : bytes_wanted = 2 * b->bytes_alloc;
522 2 : free_buffer (b);
523 2 : free (b);
524 : }
525 :
526 40 : if (lines_found)
527 24 : save_buffer (b);
528 : else
529 16 : free (b);
530 :
531 40 : return lines_found != 0;
532 : }
533 :
534 : /* Return the line number of the first line that has not yet been retrieved. */
535 :
536 : static uintmax_t
537 24 : get_first_line_in_buffer (void)
538 : {
539 24 : if (head == NULL && !load_buffer ())
540 0 : error (EXIT_FAILURE, errno, _("input disappeared"));
541 :
542 23 : return head->first_available;
543 : }
544 :
545 : /* Return a pointer to the logical first line in the buffer and make the
546 : next line the logical first line.
547 : Return NULL if there is no more input. */
548 :
549 : static struct cstring *
550 153 : remove_line (void)
551 : {
552 : /* If non-NULL, this is the buffer for which the previous call
553 : returned the final line. So now, presuming that line has been
554 : processed, we can free the buffer and reset this pointer. */
555 : static struct buffer_record *prev_buf = NULL;
556 :
557 : struct cstring *line; /* Return value. */
558 : struct line *l; /* For convenience. */
559 :
560 153 : if (prev_buf)
561 : {
562 23 : free_buffer (prev_buf);
563 23 : prev_buf = NULL;
564 : }
565 :
566 153 : if (head == NULL && !load_buffer ())
567 20 : return NULL;
568 :
569 133 : if (current_line < head->first_available)
570 112 : current_line = head->first_available;
571 :
572 133 : ++(head->first_available);
573 :
574 133 : l = head->curr_line;
575 :
576 133 : line = &l->starts[l->retrieve_index];
577 :
578 : /* Advance index to next line. */
579 133 : if (++l->retrieve_index == l->used)
580 : {
581 : /* Go on to the next line record. */
582 24 : head->curr_line = l->next;
583 24 : if (head->curr_line == NULL || head->curr_line->used == 0)
584 : {
585 : /* Go on to the next data block.
586 : but first record the current one so we can free it
587 : once the line we're returning has been processed. */
588 24 : prev_buf = head;
589 24 : head = head->next;
590 : }
591 : }
592 :
593 133 : return line;
594 : }
595 :
596 : /* Search the buffers for line LINENUM, reading more input if necessary.
597 : Return a pointer to the line, or NULL if it is not found in the file. */
598 :
599 : static struct cstring *
600 27 : find_line (uintmax_t linenum)
601 : {
602 : struct buffer_record *b;
603 :
604 27 : if (head == NULL && !load_buffer ())
605 1 : return NULL;
606 :
607 24 : if (linenum < head->start_line)
608 0 : return NULL;
609 :
610 24 : for (b = head;;)
611 : {
612 26 : if (linenum < b->start_line + b->num_lines)
613 : {
614 : /* The line is in this buffer. */
615 : struct line *l;
616 : size_t offset; /* How far into the buffer the line is. */
617 :
618 22 : l = b->line_start;
619 22 : offset = linenum - b->start_line;
620 : /* Find the control record. */
621 44 : while (offset >= CTRL_SIZE)
622 : {
623 0 : l = l->next;
624 0 : offset -= CTRL_SIZE;
625 : }
626 22 : return &l->starts[offset];
627 : }
628 3 : if (b->next == NULL && !load_buffer ())
629 2 : return NULL;
630 1 : b = b->next; /* Try the next data block. */
631 : }
632 : }
633 :
634 : /* Return true if at least one more line is available for input. */
635 :
636 : static bool
637 2 : no_more_lines (void)
638 : {
639 2 : return find_line (current_line + 1) == NULL;
640 : }
641 :
642 : /* Open NAME as standard input. */
643 :
644 : static void
645 59 : set_input_file (const char *name)
646 : {
647 59 : if (! STREQ (name, "-") && fd_reopen (STDIN_FILENO, name, O_RDONLY, 0) < 0)
648 5 : error (EXIT_FAILURE, errno, _("cannot open %s for reading"), quote (name));
649 54 : }
650 :
651 : /* Write all lines from the beginning of the buffer up to, but
652 : not including, line LAST_LINE, to the current output file.
653 : If IGNORE is true, do not output lines selected here.
654 : ARGNUM is the index in ARGV of the current pattern. */
655 :
656 : static void
657 21 : write_to_file (uintmax_t last_line, bool ignore, int argnum)
658 : {
659 : struct cstring *line;
660 : uintmax_t first_line; /* First available input line. */
661 : uintmax_t lines; /* Number of lines to output. */
662 : uintmax_t i;
663 :
664 21 : first_line = get_first_line_in_buffer ();
665 :
666 21 : if (first_line > last_line)
667 : {
668 0 : error (0, 0, _("%s: line number out of range"), global_argv[argnum]);
669 0 : cleanup_fatal ();
670 : }
671 :
672 21 : lines = last_line - first_line;
673 :
674 23 : for (i = 0; i < lines; i++)
675 : {
676 2 : line = remove_line ();
677 2 : if (line == NULL)
678 : {
679 0 : error (0, 0, _("%s: line number out of range"), global_argv[argnum]);
680 0 : cleanup_fatal ();
681 : }
682 2 : if (!ignore)
683 2 : save_line_to_file (line);
684 : }
685 21 : }
686 :
687 : /* Output any lines left after all regexps have been processed. */
688 :
689 : static void
690 20 : dump_rest_of_file (void)
691 : {
692 : struct cstring *line;
693 :
694 163 : while ((line = remove_line ()) != NULL)
695 123 : save_line_to_file (line);
696 20 : }
697 :
698 : /* Handle an attempt to read beyond EOF under the control of record P,
699 : on iteration REPETITION if nonzero. */
700 :
701 : static void handle_line_error (const struct control *, uintmax_t)
702 : ATTRIBUTE_NORETURN;
703 : static void
704 1 : handle_line_error (const struct control *p, uintmax_t repetition)
705 : {
706 : char buf[INT_BUFSIZE_BOUND (uintmax_t)];
707 :
708 1 : fprintf (stderr, _("%s: %s: line number out of range"),
709 1 : program_name, quote (umaxtostr (p->lines_required, buf)));
710 1 : if (repetition)
711 0 : fprintf (stderr, _(" on repetition %s\n"), umaxtostr (repetition, buf));
712 : else
713 1 : fprintf (stderr, "\n");
714 :
715 1 : cleanup_fatal ();
716 : }
717 :
718 : /* Determine the line number that marks the end of this file,
719 : then get those lines and save them to the output file.
720 : P is the control record.
721 : REPETITION is the repetition number. */
722 :
723 : static void
724 3 : process_line_count (const struct control *p, uintmax_t repetition)
725 : {
726 : uintmax_t linenum;
727 3 : uintmax_t last_line_to_save = p->lines_required * (repetition + 1);
728 : struct cstring *line;
729 :
730 3 : create_output_file ();
731 :
732 3 : linenum = get_first_line_in_buffer ();
733 :
734 12 : while (linenum++ < last_line_to_save)
735 : {
736 8 : line = remove_line ();
737 8 : if (line == NULL)
738 0 : handle_line_error (p, repetition);
739 8 : save_line_to_file (line);
740 : }
741 :
742 2 : close_output_file ();
743 :
744 : /* Ensure that the line number specified is not 1 greater than
745 : the number of lines in the file. */
746 2 : if (no_more_lines ())
747 1 : handle_line_error (p, repetition);
748 1 : }
749 :
750 : static void regexp_error (struct control *, uintmax_t, bool) ATTRIBUTE_NORETURN;
751 : static void
752 2 : regexp_error (struct control *p, uintmax_t repetition, bool ignore)
753 : {
754 2 : fprintf (stderr, _("%s: %s: match not found"),
755 2 : program_name, quote (global_argv[p->argnum]));
756 :
757 2 : if (repetition)
758 : {
759 : char buf[INT_BUFSIZE_BOUND (uintmax_t)];
760 0 : fprintf (stderr, _(" on repetition %s\n"), umaxtostr (repetition, buf));
761 : }
762 : else
763 2 : fprintf (stderr, "\n");
764 :
765 2 : if (!ignore)
766 : {
767 2 : dump_rest_of_file ();
768 2 : close_output_file ();
769 : }
770 2 : cleanup_fatal ();
771 : }
772 :
773 : /* Read the input until a line matches the regexp in P, outputting
774 : it unless P->IGNORE is true.
775 : REPETITION is this repeat-count; 0 means the first time. */
776 :
777 : static void
778 25 : process_regexp (struct control *p, uintmax_t repetition)
779 : {
780 : struct cstring *line; /* From input file. */
781 : size_t line_len; /* To make "$" in regexps work. */
782 : uintmax_t break_line; /* First line number of next file. */
783 25 : bool ignore = p->ignore; /* If true, skip this section. */
784 : regoff_t ret;
785 :
786 25 : if (!ignore)
787 22 : create_output_file ();
788 :
789 : /* If there is no offset for the regular expression, or
790 : it is positive, then it is not necessary to buffer the lines. */
791 :
792 25 : if (p->offset >= 0)
793 : {
794 : for (;;)
795 : {
796 25 : line = find_line (++current_line);
797 23 : if (line == NULL)
798 : {
799 2 : if (p->repeat_forever)
800 : {
801 0 : if (!ignore)
802 : {
803 0 : dump_rest_of_file ();
804 0 : close_output_file ();
805 : }
806 0 : exit (EXIT_SUCCESS);
807 : }
808 : else
809 2 : regexp_error (p, repetition, ignore);
810 : }
811 21 : line_len = line->len;
812 21 : if (line->str[line_len - 1] == '\n')
813 18 : line_len--;
814 21 : ret = re_search (&p->re_compiled, line->str, line_len,
815 : 0, line_len, NULL);
816 21 : if (ret == -2)
817 : {
818 0 : error (0, 0, _("error in regular expression search"));
819 0 : cleanup_fatal ();
820 : }
821 21 : if (ret == -1)
822 : {
823 0 : line = remove_line ();
824 0 : if (!ignore)
825 0 : save_line_to_file (line);
826 : }
827 : else
828 21 : break;
829 : }
830 : }
831 : else
832 : {
833 : /* Buffer the lines. */
834 : for (;;)
835 : {
836 0 : line = find_line (++current_line);
837 0 : if (line == NULL)
838 : {
839 0 : if (p->repeat_forever)
840 : {
841 0 : if (!ignore)
842 : {
843 0 : dump_rest_of_file ();
844 0 : close_output_file ();
845 : }
846 0 : exit (EXIT_SUCCESS);
847 : }
848 : else
849 0 : regexp_error (p, repetition, ignore);
850 : }
851 0 : line_len = line->len;
852 0 : if (line->str[line_len - 1] == '\n')
853 0 : line_len--;
854 0 : ret = re_search (&p->re_compiled, line->str, line_len,
855 : 0, line_len, NULL);
856 0 : if (ret == -2)
857 : {
858 0 : error (0, 0, _("error in regular expression search"));
859 0 : cleanup_fatal ();
860 : }
861 0 : if (ret != -1)
862 0 : break;
863 : }
864 : }
865 :
866 : /* Account for any offset from this regexp. */
867 21 : break_line = current_line + p->offset;
868 :
869 21 : write_to_file (break_line, ignore, p->argnum);
870 :
871 21 : if (!ignore)
872 19 : close_output_file ();
873 :
874 21 : if (p->offset > 0)
875 0 : current_line = break_line;
876 21 : }
877 :
878 : /* Split the input file according to the control records we have built. */
879 :
880 : static void
881 24 : split_file (void)
882 : {
883 : size_t i;
884 :
885 46 : for (i = 0; i < control_used; i++)
886 : {
887 : uintmax_t j;
888 28 : if (controls[i].regexpr)
889 : {
890 71 : for (j = 0; (controls[i].repeat_forever
891 67 : || j <= controls[i].repeat); j++)
892 25 : process_regexp (&controls[i], j);
893 : }
894 : else
895 : {
896 7 : for (j = 0; (controls[i].repeat_forever
897 5 : || j <= controls[i].repeat); j++)
898 3 : process_line_count (&controls[i], j);
899 : }
900 : }
901 :
902 18 : create_output_file ();
903 18 : dump_rest_of_file ();
904 18 : close_output_file ();
905 18 : }
906 :
907 : /* Return the name of output file number NUM.
908 :
909 : This function is called from a signal handler, so it should invoke
910 : only reentrant functions that are async-signal-safe. POSIX does
911 : not guarantee this for the functions called below, but we don't
912 : know of any hosts where this implementation isn't safe. */
913 :
914 : static char *
915 50 : make_filename (unsigned int num)
916 : {
917 50 : strcpy (filename_space, prefix);
918 50 : if (suffix)
919 12 : sprintf (filename_space + strlen (prefix), suffix, num);
920 : else
921 38 : sprintf (filename_space + strlen (prefix), "%0*u", digits, num);
922 50 : return filename_space;
923 : }
924 :
925 : /* Create the next output file. */
926 :
927 : static void
928 43 : create_output_file (void)
929 : {
930 : sigset_t oldset;
931 : bool fopen_ok;
932 : int fopen_errno;
933 :
934 43 : output_filename = make_filename (files_created);
935 :
936 : /* Create the output file in a critical section, to avoid races. */
937 43 : sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
938 43 : output_stream = fopen (output_filename, "w");
939 43 : fopen_ok = (output_stream != NULL);
940 43 : fopen_errno = errno;
941 43 : files_created += fopen_ok;
942 43 : sigprocmask (SIG_SETMASK, &oldset, NULL);
943 :
944 43 : if (! fopen_ok)
945 : {
946 0 : error (0, fopen_errno, "%s", output_filename);
947 0 : cleanup_fatal ();
948 : }
949 43 : bytes_written = 0;
950 43 : }
951 :
952 : /* If requested, delete all the files we have created. This function
953 : must be called only from critical sections. */
954 :
955 : static void
956 6 : delete_all_files (bool in_signal_handler)
957 : {
958 : unsigned int i;
959 :
960 6 : if (! remove_files)
961 0 : return;
962 :
963 13 : for (i = 0; i < files_created; i++)
964 : {
965 7 : const char *name = make_filename (i);
966 7 : if (unlink (name) != 0 && !in_signal_handler)
967 0 : error (0, errno, "%s", name);
968 : }
969 :
970 6 : files_created = 0;
971 : }
972 :
973 : /* Close the current output file and print the count
974 : of characters in this file. */
975 :
976 : static void
977 47 : close_output_file (void)
978 : {
979 47 : if (output_stream)
980 : {
981 43 : if (ferror (output_stream))
982 : {
983 0 : error (0, 0, _("write error for %s"), quote (output_filename));
984 0 : output_stream = NULL;
985 0 : cleanup_fatal ();
986 : }
987 43 : if (fclose (output_stream) != 0)
988 : {
989 0 : error (0, errno, "%s", output_filename);
990 0 : output_stream = NULL;
991 0 : cleanup_fatal ();
992 : }
993 43 : if (bytes_written == 0 && elide_empty_files)
994 0 : {
995 : sigset_t oldset;
996 : bool unlink_ok;
997 : int unlink_errno;
998 :
999 : /* Remove the output file in a critical section, to avoid races. */
1000 0 : sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
1001 0 : unlink_ok = (unlink (output_filename) == 0);
1002 0 : unlink_errno = errno;
1003 0 : files_created -= unlink_ok;
1004 0 : sigprocmask (SIG_SETMASK, &oldset, NULL);
1005 :
1006 0 : if (! unlink_ok)
1007 0 : error (0, unlink_errno, "%s", output_filename);
1008 : }
1009 : else
1010 : {
1011 43 : if (!suppress_count)
1012 : {
1013 : char buf[INT_BUFSIZE_BOUND (uintmax_t)];
1014 43 : fprintf (stdout, "%s\n", umaxtostr (bytes_written, buf));
1015 : }
1016 : }
1017 43 : output_stream = NULL;
1018 : }
1019 47 : }
1020 :
1021 : /* Save line LINE to the output file and
1022 : increment the character count for the current file. */
1023 :
1024 : static void
1025 133 : save_line_to_file (const struct cstring *line)
1026 : {
1027 133 : fwrite (line->str, sizeof (char), line->len, output_stream);
1028 133 : bytes_written += line->len;
1029 133 : }
1030 :
1031 : /* Return a new, initialized control record. */
1032 :
1033 : static struct control *
1034 55 : new_control_record (void)
1035 : {
1036 : static size_t control_allocated = 0; /* Total space allocated. */
1037 : struct control *p;
1038 :
1039 55 : if (control_used == control_allocated)
1040 55 : controls = X2NREALLOC (controls, &control_allocated);
1041 55 : p = &controls[control_used++];
1042 55 : p->regexpr = false;
1043 55 : p->repeat = 0;
1044 55 : p->repeat_forever = false;
1045 55 : p->lines_required = 0;
1046 55 : p->offset = 0;
1047 55 : return p;
1048 : }
1049 :
1050 : /* Check if there is a numeric offset after a regular expression.
1051 : STR is the entire command line argument.
1052 : P is the control record for this regular expression.
1053 : NUM is the numeric part of STR. */
1054 :
1055 : static void
1056 0 : check_for_offset (struct control *p, const char *str, const char *num)
1057 : {
1058 0 : if (xstrtoimax (num, NULL, 10, &p->offset, "") != LONGINT_OK)
1059 0 : error (EXIT_FAILURE, 0, _("%s: integer expected after delimiter"), str);
1060 0 : }
1061 :
1062 : /* Given that the first character of command line arg STR is '{',
1063 : make sure that the rest of the string is a valid repeat count
1064 : and store its value in P.
1065 : ARGNUM is the ARGV index of STR. */
1066 :
1067 : static void
1068 2 : parse_repeat_count (int argnum, struct control *p, char *str)
1069 : {
1070 : uintmax_t val;
1071 : char *end;
1072 :
1073 2 : end = str + strlen (str) - 1;
1074 2 : if (*end != '}')
1075 1 : error (EXIT_FAILURE, 0, _("%s: `}' is required in repeat count"), str);
1076 1 : *end = '\0';
1077 :
1078 1 : if (str+1 == end-1 && *(str+1) == '*')
1079 0 : p->repeat_forever = true;
1080 : else
1081 : {
1082 1 : if (xstrtoumax (str + 1, NULL, 10, &val, "") != LONGINT_OK)
1083 : {
1084 1 : error (EXIT_FAILURE, 0,
1085 : _("%s}: integer required between `{' and `}'"),
1086 1 : global_argv[argnum]);
1087 : }
1088 0 : p->repeat = val;
1089 : }
1090 :
1091 0 : *end = '}';
1092 0 : }
1093 :
1094 : /* Extract the regular expression from STR and check for a numeric offset.
1095 : STR should start with the regexp delimiter character.
1096 : Return a new control record for the regular expression.
1097 : ARGNUM is the ARGV index of STR.
1098 : Unless IGNORE is true, mark these lines for output. */
1099 :
1100 : static struct control *
1101 32 : extract_regexp (int argnum, bool ignore, char const *str)
1102 : {
1103 : size_t len; /* Number of bytes in this regexp. */
1104 32 : char delim = *str;
1105 : char const *closing_delim;
1106 : struct control *p;
1107 : const char *err;
1108 :
1109 32 : closing_delim = strrchr (str + 1, delim);
1110 32 : if (closing_delim == NULL)
1111 4 : error (EXIT_FAILURE, 0,
1112 : _("%s: closing delimiter `%c' missing"), str, delim);
1113 :
1114 28 : len = closing_delim - str - 1;
1115 28 : p = new_control_record ();
1116 28 : p->argnum = argnum;
1117 28 : p->ignore = ignore;
1118 :
1119 28 : p->regexpr = true;
1120 28 : p->re_compiled.buffer = NULL;
1121 28 : p->re_compiled.allocated = 0;
1122 28 : p->re_compiled.fastmap = xmalloc (UCHAR_MAX + 1);
1123 28 : p->re_compiled.translate = NULL;
1124 28 : re_syntax_options =
1125 : RE_SYNTAX_POSIX_BASIC & ~RE_CONTEXT_INVALID_DUP & ~RE_NO_EMPTY_RANGES;
1126 28 : err = re_compile_pattern (str + 1, len, &p->re_compiled);
1127 28 : if (err)
1128 : {
1129 0 : error (0, 0, _("%s: invalid regular expression: %s"), str, err);
1130 0 : cleanup_fatal ();
1131 : }
1132 :
1133 28 : if (closing_delim[1])
1134 0 : check_for_offset (p, str, closing_delim + 1);
1135 :
1136 28 : return p;
1137 : }
1138 :
1139 : /* Extract the break patterns from args START through ARGC - 1 of ARGV.
1140 : After each pattern, check if the next argument is a repeat count. */
1141 :
1142 : static void
1143 54 : parse_patterns (int argc, int start, char **argv)
1144 : {
1145 : int i; /* Index into ARGV. */
1146 : struct control *p; /* New control record created. */
1147 : uintmax_t val;
1148 : static uintmax_t last_val = 0;
1149 :
1150 83 : for (i = start; i < argc; i++)
1151 : {
1152 59 : if (*argv[i] == '/' || *argv[i] == '%')
1153 : {
1154 32 : p = extract_regexp (i, *argv[i] == '%', argv[i]);
1155 : }
1156 : else
1157 : {
1158 27 : p = new_control_record ();
1159 27 : p->argnum = i;
1160 :
1161 27 : if (xstrtoumax (argv[i], NULL, 10, &val, "") != LONGINT_OK)
1162 22 : error (EXIT_FAILURE, 0, _("%s: invalid pattern"), argv[i]);
1163 5 : if (val == 0)
1164 2 : error (EXIT_FAILURE, 0,
1165 : _("%s: line number must be greater than zero"),
1166 2 : argv[i]);
1167 3 : if (val < last_val)
1168 : {
1169 : char buf[INT_BUFSIZE_BOUND (uintmax_t)];
1170 0 : error (EXIT_FAILURE, 0,
1171 : _("line number %s is smaller than preceding line number, %s"),
1172 0 : quote (argv[i]), umaxtostr (last_val, buf));
1173 : }
1174 :
1175 3 : if (val == last_val)
1176 0 : error (0, 0,
1177 : _("warning: line number %s is the same as preceding line number"),
1178 0 : quote (argv[i]));
1179 :
1180 3 : last_val = val;
1181 :
1182 3 : p->lines_required = val;
1183 : }
1184 :
1185 31 : if (i + 1 < argc && *argv[i + 1] == '{')
1186 : {
1187 : /* We have a repeat count. */
1188 2 : i++;
1189 2 : parse_repeat_count (i, p, argv[i]);
1190 : }
1191 : }
1192 24 : }
1193 :
1194 : static unsigned int
1195 21 : get_format_flags (char **format_ptr)
1196 : {
1197 21 : unsigned int count = 0;
1198 :
1199 43 : for (; **format_ptr; (*format_ptr)++)
1200 : {
1201 38 : switch (**format_ptr)
1202 : {
1203 10 : case '-':
1204 10 : break;
1205 :
1206 8 : case '+':
1207 : case ' ':
1208 8 : count |= 1;
1209 8 : break;
1210 :
1211 4 : case '#':
1212 4 : count |= 2; /* Allow for 0x prefix preceding an `x' conversion. */
1213 4 : break;
1214 :
1215 16 : default:
1216 16 : return count;
1217 : }
1218 : }
1219 5 : return count;
1220 : }
1221 :
1222 : static size_t
1223 21 : get_format_width (char **format_ptr)
1224 : {
1225 21 : unsigned long int val = 0;
1226 :
1227 21 : if (ISDIGIT (**format_ptr)
1228 11 : && (xstrtoul (*format_ptr, format_ptr, 10, &val, NULL) != LONGINT_OK
1229 : || SIZE_MAX < val))
1230 0 : error (EXIT_FAILURE, 0, _("invalid format width"));
1231 :
1232 : /* Allow for enough octal digits to represent the value of UINT_MAX,
1233 : even if the field width is less than that. */
1234 21 : return MAX (val, (sizeof (unsigned int) * CHAR_BIT + 2) / 3);
1235 : }
1236 :
1237 : static size_t
1238 21 : get_format_prec (char **format_ptr)
1239 : {
1240 21 : if (**format_ptr != '.')
1241 12 : return 0;
1242 9 : (*format_ptr)++;
1243 :
1244 9 : if (! ISDIGIT (**format_ptr))
1245 6 : return 0;
1246 : else
1247 : {
1248 : unsigned long int val;
1249 3 : if (xstrtoul (*format_ptr, format_ptr, 10, &val, NULL) != LONGINT_OK
1250 : || SIZE_MAX < val)
1251 0 : error (EXIT_FAILURE, 0, _("invalid format precision"));
1252 3 : return val;
1253 : }
1254 : }
1255 :
1256 : static void
1257 21 : get_format_conv_type (char **format_ptr)
1258 : {
1259 21 : unsigned char ch = *(*format_ptr)++;
1260 :
1261 21 : switch (ch)
1262 : {
1263 9 : case 'd':
1264 : case 'i':
1265 : case 'o':
1266 : case 'u':
1267 : case 'x':
1268 : case 'X':
1269 9 : break;
1270 :
1271 8 : case 0:
1272 8 : error (EXIT_FAILURE, 0, _("missing conversion specifier in suffix"));
1273 0 : break;
1274 :
1275 4 : default:
1276 4 : if (isprint (ch))
1277 2 : error (EXIT_FAILURE, 0,
1278 : _("invalid conversion specifier in suffix: %c"), ch);
1279 : else
1280 2 : error (EXIT_FAILURE, 0,
1281 : _("invalid conversion specifier in suffix: \\%.3o"), ch);
1282 : }
1283 9 : }
1284 :
1285 : static size_t
1286 24 : max_out (char *format)
1287 : {
1288 24 : size_t out_count = 0;
1289 24 : bool percent = false;
1290 :
1291 65 : while (*format)
1292 : {
1293 30 : if (*format++ != '%')
1294 1 : out_count++;
1295 29 : else if (*format == '%')
1296 : {
1297 7 : format++;
1298 7 : out_count++;
1299 : }
1300 : else
1301 : {
1302 22 : if (percent)
1303 1 : error (EXIT_FAILURE, 0,
1304 : _("too many %% conversion specifications in suffix"));
1305 21 : percent = true;
1306 21 : out_count += get_format_flags (&format);
1307 : {
1308 21 : size_t width = get_format_width (&format);
1309 21 : size_t prec = get_format_prec (&format);
1310 :
1311 21 : out_count += MAX (width, prec);
1312 : }
1313 21 : get_format_conv_type (&format);
1314 : }
1315 : }
1316 :
1317 11 : if (! percent)
1318 3 : error (EXIT_FAILURE, 0,
1319 : _("missing %% conversion specification in suffix"));
1320 :
1321 8 : return out_count;
1322 : }
1323 :
1324 : int
1325 119 : main (int argc, char **argv)
1326 : {
1327 : int optc;
1328 : unsigned long int val;
1329 :
1330 : initialize_main (&argc, &argv);
1331 119 : program_name = argv[0];
1332 119 : setlocale (LC_ALL, "");
1333 : bindtextdomain (PACKAGE, LOCALEDIR);
1334 : textdomain (PACKAGE);
1335 :
1336 119 : atexit (close_stdout);
1337 :
1338 119 : global_argv = argv;
1339 119 : controls = NULL;
1340 119 : control_used = 0;
1341 119 : suppress_count = false;
1342 119 : remove_files = true;
1343 119 : prefix = DEFAULT_PREFIX;
1344 :
1345 278 : while ((optc = getopt_long (argc, argv, "f:b:kn:sqz", longopts, NULL)) != -1)
1346 58 : switch (optc)
1347 : {
1348 4 : case 'f':
1349 4 : prefix = optarg;
1350 4 : break;
1351 :
1352 25 : case 'b':
1353 25 : suffix = optarg;
1354 25 : break;
1355 :
1356 4 : case 'k':
1357 4 : remove_files = false;
1358 4 : break;
1359 :
1360 9 : case 'n':
1361 9 : if (xstrtoul (optarg, NULL, 10, &val, "") != LONGINT_OK
1362 2 : || val > INT_MAX)
1363 7 : error (EXIT_FAILURE, 0, _("%s: invalid number"), optarg);
1364 2 : digits = val;
1365 2 : break;
1366 :
1367 4 : case 's':
1368 : case 'q':
1369 4 : suppress_count = true;
1370 4 : break;
1371 :
1372 1 : case 'z':
1373 1 : elide_empty_files = true;
1374 1 : break;
1375 :
1376 1 : case_GETOPT_HELP_CHAR;
1377 :
1378 1 : case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1379 :
1380 9 : default:
1381 9 : usage (EXIT_FAILURE);
1382 : }
1383 :
1384 101 : if (argc - optind < 2)
1385 : {
1386 26 : if (argc <= optind)
1387 11 : error (0, 0, _("missing operand"));
1388 : else
1389 15 : error (0, 0, _("missing operand after %s"), quote (argv[argc - 1]));
1390 26 : usage (EXIT_FAILURE);
1391 : }
1392 :
1393 75 : if (suffix)
1394 24 : filename_space = xmalloc (strlen (prefix) + max_out (suffix) + 2);
1395 : else
1396 51 : filename_space = xmalloc (strlen (prefix) + digits + 2);
1397 :
1398 59 : set_input_file (argv[optind++]);
1399 :
1400 54 : parse_patterns (argc, optind, argv);
1401 :
1402 : {
1403 : int i;
1404 : static int const sig[] =
1405 : {
1406 : /* The usual suspects. */
1407 : SIGALRM, SIGHUP, SIGINT, SIGPIPE, SIGQUIT, SIGTERM,
1408 : #ifdef SIGPOLL
1409 : SIGPOLL,
1410 : #endif
1411 : #ifdef SIGPROF
1412 : SIGPROF,
1413 : #endif
1414 : #ifdef SIGVTALRM
1415 : SIGVTALRM,
1416 : #endif
1417 : #ifdef SIGXCPU
1418 : SIGXCPU,
1419 : #endif
1420 : #ifdef SIGXFSZ
1421 : SIGXFSZ,
1422 : #endif
1423 : };
1424 : enum { nsigs = sizeof sig / sizeof sig[0] };
1425 :
1426 : #if SA_NOCLDSTOP
1427 : struct sigaction act;
1428 :
1429 24 : sigemptyset (&caught_signals);
1430 288 : for (i = 0; i < nsigs; i++)
1431 : {
1432 264 : sigaction (sig[i], NULL, &act);
1433 264 : if (act.sa_handler != SIG_IGN)
1434 264 : sigaddset (&caught_signals, sig[i]);
1435 : }
1436 :
1437 24 : act.sa_handler = interrupt_handler;
1438 24 : act.sa_mask = caught_signals;
1439 24 : act.sa_flags = 0;
1440 :
1441 288 : for (i = 0; i < nsigs; i++)
1442 264 : if (sigismember (&caught_signals, sig[i]))
1443 264 : sigaction (sig[i], &act, NULL);
1444 : #else
1445 : for (i = 0; i < nsigs; i++)
1446 : if (signal (sig[i], SIG_IGN) != SIG_IGN)
1447 : {
1448 : signal (sig[i], interrupt_handler);
1449 : siginterrupt (sig[i], 1);
1450 : }
1451 : #endif
1452 : }
1453 :
1454 24 : split_file ();
1455 :
1456 18 : if (close (STDIN_FILENO) != 0)
1457 : {
1458 0 : error (0, errno, _("read error"));
1459 0 : cleanup_fatal ();
1460 : }
1461 :
1462 18 : exit (EXIT_SUCCESS);
1463 : }
1464 :
1465 : void
1466 36 : usage (int status)
1467 : {
1468 36 : if (status != EXIT_SUCCESS)
1469 35 : fprintf (stderr, _("Try `%s --help' for more information.\n"),
1470 : program_name);
1471 : else
1472 : {
1473 1 : printf (_("\
1474 : Usage: %s [OPTION]... FILE PATTERN...\n\
1475 : "),
1476 : program_name);
1477 1 : fputs (_("\
1478 : Output pieces of FILE separated by PATTERN(s) to files `xx00', `xx01', ...,\n\
1479 : and output byte counts of each piece to standard output.\n\
1480 : \n\
1481 : "), stdout);
1482 1 : fputs (_("\
1483 : Mandatory arguments to long options are mandatory for short options too.\n\
1484 : "), stdout);
1485 1 : fputs (_("\
1486 : -b, --suffix-format=FORMAT use sprintf FORMAT instead of %02d\n\
1487 : -f, --prefix=PREFIX use PREFIX instead of `xx'\n\
1488 : -k, --keep-files do not remove output files on errors\n\
1489 : "), stdout);
1490 1 : fputs (_("\
1491 : -n, --digits=DIGITS use specified number of digits instead of 2\n\
1492 : -s, --quiet, --silent do not print counts of output file sizes\n\
1493 : -z, --elide-empty-files remove empty output files\n\
1494 : "), stdout);
1495 1 : fputs (HELP_OPTION_DESCRIPTION, stdout);
1496 1 : fputs (VERSION_OPTION_DESCRIPTION, stdout);
1497 1 : fputs (_("\
1498 : \n\
1499 : Read standard input if FILE is -. Each PATTERN may be:\n\
1500 : "), stdout);
1501 1 : fputs (_("\
1502 : \n\
1503 : INTEGER copy up to but not including specified line number\n\
1504 : /REGEXP/[OFFSET] copy up to but not including a matching line\n\
1505 : %REGEXP%[OFFSET] skip to, but not including a matching line\n\
1506 : {INTEGER} repeat the previous pattern specified number of times\n\
1507 : {*} repeat the previous pattern as many times as possible\n\
1508 : \n\
1509 : A line OFFSET is a required `+' or `-' followed by a positive integer.\n\
1510 : "), stdout);
1511 1 : emit_bug_reporting_address ();
1512 : }
1513 36 : exit (status);
1514 : }
|