1 /* $OpenBSD: cut.c,v 1.25 2018/07/13 08:51:14 krw Exp $ */
2 /* $NetBSD: cut.c,v 1.9 1995/09/02 05:59:23 jtc Exp $ */
5 * Copyright (c) 1989, 1993
6 * The Regents of the University of California. All rights reserved.
8 * This code is derived from software contributed to Berkeley by
9 * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 void b_cut(FILE *, char *);
58 void c_cut(FILE *, char *);
59 void f_cut(FILE *, char *);
60 void get_list(char *);
64 main(int argc
, char *argv
[])
67 void (*fcn
)(FILE *, char *);
70 setlocale(LC_CTYPE
, "");
72 if (pledge("stdio rpath", NULL
) == -1)
75 dchar
[0] = '\t'; /* default delimiter */
79 while ((ch
= getopt(argc
, argv
, "b:c:d:f:sn")) != -1)
90 if ((dlen
= mblen(optarg
, MB_CUR_MAX
)) == -1)
92 assert(dlen
< sizeof(dchar
));
93 (void)memcpy(dchar
, optarg
, dlen
);
114 if (bflag
+ cflag
+ fflag
!= 1 ||
116 ((dflag
|| sflag
) && !fflag
))
119 if (MB_CUR_MAX
== 1) {
127 fcn
= fflag
? f_cut
: (cflag
|| nflag
) ? c_cut
: b_cut
;
131 for (; *argv
; ++argv
) {
132 if (strcmp(*argv
, "-") == 0)
135 if ((fp
= fopen(*argv
, "r"))) {
145 if (pledge("stdio rpath", NULL
) == -1)
153 int autostart
, autostop
, maxval
;
155 char positions
[_POSIX2_LINE_MAX
+ 1];
158 read_number(char **p
)
164 q
= *p
+ strcspn(*p
, "-");
167 n
= strtonum(*p
, 1, _POSIX2_LINE_MAX
, &errstr
);
169 errx(1, "[-bcf] list: %s %s (allowed 1-%d)", *p
, errstr
,
181 int setautostart
, start
, stop
;
185 * set a byte in the positions array to indicate if a field or
186 * column is to be selected; use +1, it's 1-based, not 0-based.
187 * This parser is less restrictive than the Draft 9 POSIX spec.
188 * POSIX doesn't allow lists that aren't in increasing order or
189 * overlapping lists. We also handle "-3-5" although there's no
192 while ((p
= strsep(&list
, ", \t"))) {
193 setautostart
= start
= stop
= 0;
198 if (isdigit((unsigned char)*p
)) {
199 start
= stop
= read_number(&p
);
200 if (setautostart
&& start
> autostart
)
204 if (isdigit((unsigned char)p
[1])) {
206 stop
= read_number(&p
);
210 if (!autostop
|| autostop
> stop
)
214 if (*p
!= '\0' || !stop
|| !start
)
215 errx(1, "[-bcf] list: illegal list value");
219 memset(positions
+ start
, 1, stop
- start
+ 1);
222 /* overlapping ranges */
223 if (autostop
&& maxval
> autostop
)
228 memset(positions
+ 1, '1', autostart
);
233 b_cut(FILE *fp
, char *fname
)
241 for (col
= maxval
; col
; --col
) {
242 if ((ch
= getc(fp
)) == EOF
)
251 while ((ch
= getc(fp
)) != EOF
&& ch
!= '\n')
254 while ((ch
= getc(fp
)) != EOF
&& ch
!= '\n')
262 c_cut(FILE *fp
, char *fname
)
264 static char *line
= NULL
;
265 static size_t linesz
= 0;
267 char *cp
, *pos
, *maxpos
;
270 while ((linelen
= getline(&line
, &linesz
, fp
)) != -1) {
271 if (line
[linelen
- 1] == '\n')
272 line
[linelen
- 1] = '\0';
276 maxpos
= pos
+ maxval
;
277 while(pos
< maxpos
&& *cp
!= '\0') {
278 len
= mblen(cp
, MB_CUR_MAX
);
281 pos
+= nflag
? len
: 1;
296 f_cut(FILE *fp
, char *fname
)
298 static char *line
= NULL
;
299 static size_t linesz
= 0;
301 char *sp
, *ep
, *pos
, *maxpos
;
304 while ((linelen
= getline(&line
, &linesz
, fp
)) != -1) {
305 if (line
[linelen
- 1] == '\n')
306 line
[linelen
- 1] = '\0';
308 if ((ep
= strstr(line
, dchar
)) == NULL
) {
315 maxpos
= pos
+ maxval
;
321 fputs(dchar
, stdout
);
327 if (*sp
== '\0' || pos
== maxpos
)
330 if ((ep
= strstr(sp
, dchar
)) == NULL
)
331 ep
= strchr(sp
, '\0');
343 (void)fprintf(stderr
,
344 "usage: cut -b list [-n] [file ...]\n"
345 " cut -c list [file ...]\n"
346 " cut -f list [-s] [-d delim] [file ...]\n");