(usage): Include one- or two-line synopsis in --help output.
[platform/upstream/coreutils.git] / src / cut.c
1 /* cut - remove parts of lines of files
2    Copyright (C) 1984 by David M. Ihnat
3
4    This program is a total rewrite of the Bell Laboratories Unix(Tm)
5    command of the same name, as of System V.  It contains no proprietary
6    code, and therefore may be used without violation of any proprietary
7    agreements whatsoever.  However, you will notice that the program is
8    copyrighted by me.  This is to assure the program does *not* fall
9    into the public domain.  Thus, I may specify just what I am now:
10    This program may be freely copied and distributed, provided this notice
11    remains; it may not be sold for profit without express written consent of
12    the author.
13    Please note that I recreated the behavior of the Unix(Tm) 'cut' command
14    as faithfully as possible; however, I haven't run a full set of regression
15    tests.  Thus, the user of this program accepts full responsibility for any
16    effects or loss; in particular, the author is not responsible for any losses,
17    explicit or incidental, that may be incurred through use of this program.
18
19    I ask that any bugs (and, if possible, fixes) be reported to me when
20    possible.  -David Ihnat (312) 784-4544 ignatz@homebru.chi.il.us
21
22    POSIX changes, bug fixes, long-named options, and cleanup
23    by David MacKenzie <djm@gnu.ai.mit.edu>.
24
25    Rewrite cut_fields and cut_bytes -- Jim Meyering (meyering@comco.com).
26
27    Options:
28    --bytes=byte-list
29    -b byte-list                 Print only the bytes in positions listed
30                                 in BYTE-LIST.
31                                 Tabs and backspaces are treated like any
32                                 other character; they take up 1 byte.
33
34    --characters=character-list
35    -c character-list            Print only characters in positions listed
36                                 in CHARACTER-LIST.
37                                 The same as -b for now, but
38                                 internationalization will change that.
39                                 Tabs and backspaces are treated like any
40                                 other character; they take up 1 character.
41
42    --fields=field-list
43    -f field-list                Print only the fields listed in FIELD-LIST.
44                                 Fields are separated by a TAB by default.
45
46    --delimiter=delim
47    -d delim                     For -f, fields are separated by the first
48                                 character in DELIM instead of TAB.
49
50    -n                           Do not split multibyte chars (no-op for now).
51
52    --only-delimited
53    -s                           For -f, do not print lines that do not contain
54                                 the field separator character.
55
56    The BYTE-LIST, CHARACTER-LIST, and FIELD-LIST are one or more numbers
57    or ranges separated by commas.  The first byte, character, and field
58    are numbered 1.
59
60    A FILE of `-' means standard input. */
61
62 #include <config.h>
63
64 /* Get isblank from GNU libc.  */
65 #define _GNU_SOURCE
66
67 #include <stdio.h>
68
69 #define NDEBUG
70 #include <assert.h>
71
72 #include <getopt.h>
73 #include <sys/types.h>
74 #include "system.h"
75 #include "version.h"
76 #include "error.h"
77
78 #define FATAL_ERROR(s)                                                  \
79   do                                                                    \
80     {                                                                   \
81       error (0, 0, (s));                                                \
82       usage (2);                                                        \
83     }                                                                   \
84   while (0)
85
86 /* Append LOW, HIGH to the list RP of range pairs, allocating additional
87    space if necessary.  Update local variable N_RP.  When allocating,
88    update global variable N_RP_ALLOCATED.  */
89
90 #define ADD_RANGE_PAIR(rp, low, high)                                   \
91   do                                                                    \
92     {                                                                   \
93       if (n_rp >= n_rp_allocated)                                       \
94         {                                                               \
95           n_rp_allocated *= 2;                                          \
96           (rp) = (struct range_pair *) xrealloc ((rp),                  \
97                                    n_rp_allocated * sizeof (*(rp)));    \
98         }                                                               \
99       rp[n_rp].lo = (low);                                              \
100       rp[n_rp].hi = (high);                                             \
101       ++n_rp;                                                           \
102     }                                                                   \
103   while (0)
104
105 struct range_pair
106   {
107     int lo;
108     int hi;
109   };
110
111 char *xmalloc ();
112 char *xrealloc ();
113
114 /* This buffer is used to support the semantics of the -s option
115    (or lack of same) when the specified field list includes (does
116    not include) the first field.  In both of those cases, the entire
117    first field must be read into this buffer to determine whether it
118    is followed by a delimiter or a newline before any of it may be
119    output.  Otherwise, cut_fields can do the job without using this
120    buffer.  */
121 static char *field_1_buffer;
122
123 /* The number of bytes allocated for FIELD_1_BUFFER.  */
124 static int field_1_bufsize;
125
126 /* The largest field or byte index used as an endpoint of a closed
127    or degenerate range specification;  this doesn't include the starting
128    index of right-open-ended ranges.  For example, with either range spec
129    `2-5,9-', `2-3,5,9-' this variable would be set to 5.  */
130 static int max_range_endpoint;
131
132 /* If nonzero, this is the index of the first field in a range that goes
133    to end of line. */
134 static int eol_range_start;
135
136 /* In byte mode, which bytes to output.
137    In field mode, which DELIM-separated fields to output.
138    Both bytes and fields are numbered starting with 1,
139    so the zeroth element of this array is unused.
140    A field or byte K has been selected if
141    (K <= MAX_RANGE_ENDPOINT and PRINTABLE_FIELD[K])
142     || (EOL_RANGE_START > 0 && K >= EOL_RANGE_START).  */
143 static int *printable_field;
144
145 enum operating_mode
146   {
147     undefined_mode,
148
149     /* Output characters that are in the given bytes. */
150     byte_mode,
151
152     /* Output the given delimeter-separated fields. */
153     field_mode
154   };
155
156 /* The name this program was run with. */
157 char *program_name;
158
159 static enum operating_mode operating_mode;
160
161 /* If non-zero do not output lines containing no delimeter characters.
162    Otherwise, all such lines are printed.  This option is valid only
163    with field mode.  */
164 static int suppress_non_delimited;
165
166 /* The delimeter character for field mode. */
167 static int delim;
168
169 /* Nonzero if we have ever read standard input. */
170 static int have_read_stdin;
171
172 /* If non-zero, display usage information and exit.  */
173 static int show_help;
174
175 /* If non-zero, print the version on standard output then exit.  */
176 static int show_version;
177
178 static struct option const longopts[] =
179 {
180   {"bytes", required_argument, 0, 'b'},
181   {"characters", required_argument, 0, 'c'},
182   {"fields", required_argument, 0, 'f'},
183   {"delimiter", required_argument, 0, 'd'},
184   {"only-delimited", no_argument, 0, 's'},
185   {"help", no_argument, &show_help, 1},
186   {"version", no_argument, &show_version, 1},
187   {0, 0, 0, 0}
188 };
189
190 static void
191 usage (status)
192      int status;
193 {
194   if (status != 0)
195     fprintf (stderr, "Try `%s --help' for more information.\n",
196              program_name);
197   else
198     {
199       printf ("\
200 Usage: %s [OPTION]... [FILE]...\n\
201 ",
202               program_name);
203       printf ("\
204 Print selected parts of lines from each FILE to standard output.\n\
205 \n\
206   -b, --bytes=LIST        output only these bytes\n\
207   -c, --characters=LIST   output only these characters\n\
208   -d, --delimiter=DELIM   use DELIM instead of TAB for field delimiter\n\
209   -f, --fields=LIST       output only these fields\n\
210   -n                      (ignored)\n\
211   -s, --only-delimited    do not print lines not containing delimiters\n\
212       --help              display this help and exit\n\
213       --version           output version information and exit\n\
214 \n\
215 Use one, and only one of -b, -c or -f.  Each LIST is made up of one\n\
216 range, or many ranges separated by commas.  Each range is one of:\n\
217 \n\
218   N     N'th byte, character or field, counted from 1\n\
219   N-    from N'th byte, character or field, to end of line\n\
220   N-M   from N'th to M'th (included) byte, character or field\n\
221   -M    from first to M'th (included) byte, character or field\n\
222 \n\
223 With no FILE, or when FILE is -, read standard input.\n\
224 ");
225     }
226   exit (status);
227 }
228
229 /* The following function was copied from getline.c, but with these changes:
230    - Read up to and including a newline or TERMINATOR, whichever comes first.
231    The original does not treat newline specially.
232    - Remove unused argument, OFFSET.
233    - Use xmalloc and xrealloc instead of malloc and realloc.
234    - Declare this function static.  */
235
236 /* Always add at least this many bytes when extending the buffer.  */
237 #define MIN_CHUNK 64
238
239 /* Read up to (and including) a newline or TERMINATOR from STREAM into
240    *LINEPTR (and null-terminate it). *LINEPTR is a pointer returned from
241    xmalloc (or NULL), pointing to *N characters of space.  It is
242    xrealloc'd as necessary.  Return the number of characters read (not
243    including the null terminator), or -1 on error or EOF.  */
244
245 static int
246 getstr (lineptr, n, stream, terminator)
247      char **lineptr;
248      int *n;
249      FILE *stream;
250      char terminator;
251 {
252   int nchars_avail;             /* Allocated but unused chars in *LINEPTR.  */
253   char *read_pos;               /* Where we're reading into *LINEPTR. */
254
255   if (!lineptr || !n || !stream)
256     return -1;
257
258   if (!*lineptr)
259     {
260       *n = MIN_CHUNK;
261       *lineptr = xmalloc (*n);
262       if (!*lineptr)
263         return -1;
264     }
265
266   nchars_avail = *n;
267   read_pos = *lineptr;
268
269   for (;;)
270     {
271       register int c = getc (stream);
272
273       /* We always want at least one char left in the buffer, since we
274          always (unless we get an error while reading the first char)
275          NUL-terminate the line buffer.  */
276
277       assert (*n - nchars_avail == read_pos - *lineptr);
278       if (nchars_avail < 1)
279         {
280           if (*n > MIN_CHUNK)
281             *n *= 2;
282           else
283             *n += MIN_CHUNK;
284
285           nchars_avail = *n + *lineptr - read_pos;
286           *lineptr = xrealloc (*lineptr, *n);
287           if (!*lineptr)
288             return -1;
289           read_pos = *n - nchars_avail + *lineptr;
290           assert (*n - nchars_avail == read_pos - *lineptr);
291         }
292
293       if (feof (stream) || ferror (stream))
294         {
295           /* Return partial line, if any.  */
296           if (read_pos == *lineptr)
297             return -1;
298           else
299             break;
300         }
301
302       *read_pos++ = c;
303       nchars_avail--;
304
305       if (c == terminator || c == '\n')
306         /* Return the line.  */
307         break;
308     }
309
310   /* Done - NUL terminate and return the number of chars read.  */
311   *read_pos = '\0';
312
313   return read_pos - *lineptr;
314 }
315
316 static int
317 print_kth (k)
318      int k;
319 {
320   return ((eol_range_start > 0 && eol_range_start <= k)
321           || (k <= max_range_endpoint && printable_field[k]));
322 }
323
324 /* Given the list of field or byte range specifications FIELDSTR, set
325    MAX_RANGE_ENDPOINT and allocate and initialize the PRINTABLE_FIELD
326    array.  If there is a right-open-ended range, set EOL_RANGE_START
327    to its starting index.  FIELDSTR should be composed of one or more
328    numbers or ranges of numbers, separated by blanks or commas.
329    Incomplete ranges may be given: `-m' means `1-m'; `n-' means `n'
330    through end of line.  Return non-zero if FIELDSTR contains at least
331    one field specification, zero otherwise.  */
332
333 /* FIXME-someday:  What if the user wants to cut out the 1,000,000-th field
334    of some huge input file?  This function shouldn't have to alloate a table
335    of a million ints just so we can test every field < 10^6 with an array
336    dereference.  Instead, consider using a dynamic hash table.  It would be
337    simpler and nearly as good a solution to use a 32K x 4-byte table with
338    one bit per field index instead of a whole `int' per index.  */
339
340 static int
341 set_fields (fieldstr)
342      const char *fieldstr;
343 {
344   int initial = 1;              /* Value of first number in a range.  */
345   int dash_found = 0;           /* Nonzero if a '-' is found in this field.  */
346   int value = 0;                /* If nonzero, a number being accumulated.  */
347   int field_found = 0;          /* Non-zero if at least one field spec
348                                    has been processed.  */
349
350   struct range_pair *rp;
351   unsigned int n_rp;
352   unsigned int n_rp_allocated;
353   unsigned int i;
354
355   n_rp = 0;
356   n_rp_allocated = 16;
357   rp = (struct range_pair *) xmalloc (n_rp_allocated * sizeof (*rp));
358
359   /* Collect and store in RP the range end points.
360      It also sets EOL_RANGE_START if appropriate.  */
361
362   for (;;)
363     {
364       if (*fieldstr == '-')
365         {
366           /* Starting a range. */
367           if (dash_found)
368             FATAL_ERROR ("invalid byte or field list");
369           dash_found++;
370           fieldstr++;
371
372           if (value)
373             {
374               initial = value;
375               value = 0;
376             }
377           else
378             initial = 1;
379         }
380       else if (*fieldstr == ',' || ISBLANK (*fieldstr) || *fieldstr == '\0')
381         {
382           /* Ending the string, or this field/byte sublist. */
383           if (dash_found)
384             {
385               dash_found = 0;
386
387               /* A range.  Possibilites: -n, m-n, n-.
388                  In any case, `initial' contains the start of the range. */
389               if (value == 0)
390                 {
391                   /* `n-'.  From `initial' to end of line. */
392                   eol_range_start = initial;
393                   field_found = 1;
394                 }
395               else
396                 {
397                   /* `m-n' or `-n' (1-n). */
398                   if (value < initial)
399                     FATAL_ERROR ("invalid byte or field list");
400
401                   /* Is there already a range going to end of line? */
402                   if (eol_range_start != 0)
403                     {
404                       /* Yes.  Is the new sequence already contained
405                          in the old one?  If so, no processing is
406                          necessary. */
407                       if (initial < eol_range_start)
408                         {
409                           /* No, the new sequence starts before the
410                              old.  Does the old range going to end of line
411                              extend into the new range?  */
412                           if (value >= eol_range_start - 1)
413                             {
414                               /* Yes.  Simply move the end of line marker. */
415                               eol_range_start = initial;
416                             }
417                           else
418                             {
419                               /* No.  A simple range, before and disjoint from
420                                  the range going to end of line.  Fill it. */
421                               ADD_RANGE_PAIR (rp, initial, value);
422                             }
423
424                           /* In any case, some fields were selected. */
425                           field_found = 1;
426                         }
427                     }
428                   else
429                     {
430                       /* There is no range going to end of line. */
431                       ADD_RANGE_PAIR (rp, initial, value);
432                       field_found = 1;
433                     }
434                   value = 0;
435                 }
436             }
437           else if (value != 0)
438             {
439               /* A simple field number, not a range. */
440               ADD_RANGE_PAIR (rp, value, value);
441               value = 0;
442               field_found = 1;
443             }
444
445           if (*fieldstr == '\0')
446             {
447               break;
448             }
449
450           fieldstr++;
451         }
452       else if (ISDIGIT (*fieldstr))
453         {
454           /* FIXME: detect overflow?  */
455           value = 10 * value + *fieldstr - '0';
456           fieldstr++;
457         }
458       else
459         FATAL_ERROR ("invalid byte or field list");
460     }
461
462   max_range_endpoint = 0;
463   for (i = 0; i < n_rp; i++)
464     {
465       if (rp[i].hi > max_range_endpoint)
466         max_range_endpoint = rp[i].hi;
467     }
468
469   /* Allocate an array large enough so that it may be indexed by
470      the field numbers corresponding to all finite ranges
471      (i.e. `2-6' or `-4', but not `5-') in FIELDSTR.  */
472
473   printable_field = (int *) xmalloc ((max_range_endpoint + 1) * sizeof (int));
474   for (i = 1; i <= max_range_endpoint; i++)
475     printable_field[i] = 0;
476
477   /* Set the array entries corresponding to integers in the ranges of RP.  */
478   for (i = 0; i < n_rp; i++)
479     {
480       int j;
481       for (j = rp[i].lo; j <= rp[i].hi; j++)
482         {
483           printable_field[j] = 1;
484         }
485     }
486
487   free (rp);
488
489   return field_found;
490 }
491
492 /* Read from stream STREAM, printing to standard output any selected bytes.  */
493
494 static void
495 cut_bytes (stream)
496      FILE *stream;
497 {
498   int byte_idx;                 /* Number of chars in the line so far. */
499
500   byte_idx = 0;
501   while (1)
502     {
503       register int c;           /* Each character from the file. */
504
505       c = getc (stream);
506
507       if (c == '\n')
508         {
509           putchar ('\n');
510           byte_idx = 0;
511         }
512       else if (c == EOF)
513         {
514           if (byte_idx > 0)
515             putchar ('\n');
516           break;
517         }
518       else
519         {
520           ++byte_idx;
521           if (print_kth (byte_idx))
522             {
523               putchar (c);
524             }
525         }
526     }
527 }
528
529 /* Read from stream STREAM, printing to standard output any selected fields.  */
530
531 static void
532 cut_fields (stream)
533      FILE *stream;
534 {
535   int c;
536   int field_idx;
537   int found_any_selected_field;
538   int buffer_first_field;
539
540   found_any_selected_field = 0;
541   field_idx = 1;
542
543   /* To support the semantics of the -s flag, we may have to buffer
544      all of the first field to determine whether it is `delimited.'
545      But that is unnecessary if all non-delimited lines must be printed
546      and the first field has been selected, or if non-delimited lines
547      must be suppressed and the first field has *not* been selected.
548      That is because a non-delimited line has exactly one field.  */
549   buffer_first_field = (suppress_non_delimited ^ !print_kth (1));
550
551   while (1)
552     {
553       if (field_idx == 1 && buffer_first_field)
554         {
555           int len;
556
557           len = getstr (&field_1_buffer, &field_1_bufsize, stream, delim);
558           if (len < 0)
559             break;
560
561           assert (len != 0);
562
563           /* If the first field extends to the end of line (it is not
564              delimited) and we are printing all non-delimited lines,
565              print this one.  */
566           if (field_1_buffer[len - 1] != delim)
567             {
568               if (suppress_non_delimited)
569                 {
570                   /* Empty.  */
571                 }
572               else
573                 {
574                   fwrite (field_1_buffer, sizeof (char), len, stdout);
575                   /* Make sure the output line is newline terminated.  */
576                   if (field_1_buffer[len - 1] != '\n')
577                     putchar ('\n');
578                 }
579               continue;
580             }
581           if (print_kth (1))
582             {
583               /* Print the field, but not the trailing delimiter.  */
584               fwrite (field_1_buffer, sizeof (char), len - 1, stdout);
585               found_any_selected_field = 1;
586             }
587           ++field_idx;
588         }
589
590       if (print_kth (field_idx))
591         {
592           if (found_any_selected_field)
593             putchar (delim);
594           found_any_selected_field = 1;
595
596           while ((c = getc (stream)) != delim && c != '\n' && c != EOF)
597             {
598               putchar (c);
599             }
600         }
601       else
602         {
603           while ((c = getc (stream)) != delim && c != '\n' && c != EOF)
604             {
605               /* Empty.  */
606             }
607         }
608
609       if (c == '\n')
610         {
611           c = getc (stream);
612           if (c != EOF)
613             {
614               ungetc (c, stream);
615               c = '\n';
616             }
617         }
618
619       if (c == delim)
620         ++field_idx;
621       else if (c == '\n' || c == EOF)
622         {
623           if (found_any_selected_field
624               || !(suppress_non_delimited && field_idx == 1))
625             putchar ('\n');
626           if (c == EOF)
627             break;
628           field_idx = 1;
629           found_any_selected_field = 0;
630         }
631     }
632 }
633
634 static void
635 cut_stream (stream)
636      FILE *stream;
637 {
638   if (operating_mode == byte_mode)
639     cut_bytes (stream);
640   else
641     cut_fields (stream);
642 }
643
644 /* Process file FILE to standard output.
645    Return 0 if successful, 1 if not. */
646
647 static int
648 cut_file (file)
649      char *file;
650 {
651   FILE *stream;
652
653   if (!strcmp (file, "-"))
654     {
655       have_read_stdin = 1;
656       stream = stdin;
657     }
658   else
659     {
660       stream = fopen (file, "r");
661       if (stream == NULL)
662         {
663           error (0, errno, "%s", file);
664           return 1;
665         }
666     }
667
668   cut_stream (stream);
669
670   if (ferror (stream))
671     {
672       error (0, errno, "%s", file);
673       return 1;
674     }
675   if (!strcmp (file, "-"))
676     clearerr (stream);          /* Also clear EOF. */
677   else if (fclose (stream) == EOF)
678     {
679       error (0, errno, "%s", file);
680       return 1;
681     }
682   return 0;
683 }
684
685 void
686 main (argc, argv)
687      int argc;
688      char **argv;
689 {
690   int optc, exit_status = 0;
691
692   program_name = argv[0];
693
694   operating_mode = undefined_mode;
695
696   /* By default, all non-delimited lines are printed.  */
697   suppress_non_delimited = 0;
698
699   delim = '\0';
700   have_read_stdin = 0;
701
702   while ((optc = getopt_long (argc, argv, "b:c:d:f:ns", longopts, (int *) 0))
703          != EOF)
704     {
705       switch (optc)
706         {
707         case 0:
708           break;
709
710         case 'b':
711         case 'c':
712           /* Build the byte list. */
713           if (operating_mode != undefined_mode)
714             FATAL_ERROR ("only one type of list may be specified");
715           operating_mode = byte_mode;
716           if (set_fields (optarg) == 0)
717             FATAL_ERROR ("missing list of positions");
718           break;
719
720         case 'f':
721           /* Build the field list. */
722           if (operating_mode != undefined_mode)
723             FATAL_ERROR ("only one type of list may be specified");
724           operating_mode = field_mode;
725           if (set_fields (optarg) == 0)
726             FATAL_ERROR ("missing list of fields");
727           break;
728
729         case 'd':
730           /* New delimiter. */
731           /* Interpret -d '' to mean `use the NUL byte as the delimiter.'  */
732           if (optarg[0] != '\0' && optarg[1] != '\0')
733             FATAL_ERROR ("the delimiter must be a single character");
734           delim = optarg[0];
735           break;
736
737         case 'n':
738           break;
739
740         case 's':
741           suppress_non_delimited = 1;
742           break;
743
744         default:
745           usage (2);
746         }
747     }
748
749   if (show_version)
750     {
751       printf ("cut - %s\n", version_string);
752       exit (0);
753     }
754
755   if (show_help)
756     usage (0);
757
758   if (operating_mode == undefined_mode)
759     FATAL_ERROR ("you must specify a list of bytes, characters, or fields");
760
761   if (delim != '\0' && operating_mode != field_mode)
762     FATAL_ERROR ("a delimiter may be specified only when operating on fields");
763
764   if (suppress_non_delimited && operating_mode != field_mode)
765     FATAL_ERROR ("suppressing non-delimited lines makes sense\n\
766 \tonly when operating on fields");
767
768   if (delim == '\0')
769     delim = '\t';
770
771   if (optind == argc)
772     exit_status |= cut_file ("-");
773   else
774     for (; optind < argc; optind++)
775       exit_status |= cut_file (argv[optind]);
776
777   if (have_read_stdin && fclose (stdin) == EOF)
778     {
779       error (0, errno, "-");
780       exit_status = 1;
781     }
782   if (ferror (stdout) || fclose (stdout) == EOF)
783     error (1, errno, "write error");
784
785   exit (exit_status);
786 }