Mercurial > docs > cut
comparison code/cut.c__openbsd.2008-06-27 @ 14:21ad1c1548c4
Code ausgewaehlter Implementierungen eingefuegt
Das Datum entspricht dem Dateiaenderungsdatum.
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Tue, 12 May 2015 06:46:59 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
13:bf5e41260f89 | 14:21ad1c1548c4 |
---|---|
1 /* $OpenBSD: cut.c,v 1.13 2008/06/27 08:02:13 sobrado Exp $ */ | |
2 /* $NetBSD: cut.c,v 1.9 1995/09/02 05:59:23 jtc Exp $ */ | |
3 | |
4 /* | |
5 * Copyright (c) 1989, 1993 | |
6 * The Regents of the University of California. All rights reserved. | |
7 * | |
8 * This code is derived from software contributed to Berkeley by | |
9 * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue. | |
10 * | |
11 * Redistribution and use in source and binary forms, with or without | |
12 * modification, are permitted provided that the following conditions | |
13 * are met: | |
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. | |
22 * | |
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 | |
33 * SUCH DAMAGE. | |
34 */ | |
35 | |
36 #ifndef lint | |
37 static char copyright[] = | |
38 "@(#) Copyright (c) 1989, 1993\n\ | |
39 The Regents of the University of California. All rights reserved.\n"; | |
40 #endif /* not lint */ | |
41 | |
42 #ifndef lint | |
43 #if 0 | |
44 static char sccsid[] = "@(#)cut.c 8.3 (Berkeley) 5/4/95"; | |
45 #endif | |
46 static char rcsid[] = "$OpenBSD: cut.c,v 1.13 2008/06/27 08:02:13 sobrado Exp $"; | |
47 #endif /* not lint */ | |
48 | |
49 #include <ctype.h> | |
50 #include <err.h> | |
51 #include <errno.h> | |
52 #include <limits.h> | |
53 #include <locale.h> | |
54 #include <stdio.h> | |
55 #include <stdlib.h> | |
56 #include <string.h> | |
57 #include <unistd.h> | |
58 | |
59 int cflag; | |
60 char dchar; | |
61 int dflag; | |
62 int fflag; | |
63 int sflag; | |
64 | |
65 void c_cut(FILE *, char *); | |
66 void f_cut(FILE *, char *); | |
67 void get_list(char *); | |
68 void usage(void); | |
69 | |
70 int | |
71 main(int argc, char *argv[]) | |
72 { | |
73 FILE *fp; | |
74 void (*fcn)(FILE *, char *); | |
75 int ch; | |
76 | |
77 setlocale (LC_ALL, ""); | |
78 | |
79 dchar = '\t'; /* default delimiter is \t */ | |
80 | |
81 /* Since we don't support multi-byte characters, the -c and -b | |
82 options are equivalent, and the -n option is meaningless. */ | |
83 while ((ch = getopt(argc, argv, "b:c:d:f:sn")) != -1) | |
84 switch(ch) { | |
85 case 'b': | |
86 case 'c': | |
87 fcn = c_cut; | |
88 get_list(optarg); | |
89 cflag = 1; | |
90 break; | |
91 case 'd': | |
92 dchar = *optarg; | |
93 dflag = 1; | |
94 break; | |
95 case 'f': | |
96 get_list(optarg); | |
97 fcn = f_cut; | |
98 fflag = 1; | |
99 break; | |
100 case 's': | |
101 sflag = 1; | |
102 break; | |
103 case 'n': | |
104 break; | |
105 case '?': | |
106 default: | |
107 usage(); | |
108 } | |
109 argc -= optind; | |
110 argv += optind; | |
111 | |
112 if (fflag) { | |
113 if (cflag) | |
114 usage(); | |
115 } else if (!cflag || dflag || sflag) | |
116 usage(); | |
117 | |
118 if (*argv) | |
119 for (; *argv; ++argv) { | |
120 if (!(fp = fopen(*argv, "r"))) | |
121 err(1, "%s", *argv); | |
122 fcn(fp, *argv); | |
123 (void)fclose(fp); | |
124 } | |
125 else | |
126 fcn(stdin, "stdin"); | |
127 exit(0); | |
128 } | |
129 | |
130 int autostart, autostop, maxval; | |
131 | |
132 char positions[_POSIX2_LINE_MAX + 1]; | |
133 | |
134 void | |
135 get_list(char *list) | |
136 { | |
137 int setautostart, start, stop; | |
138 char *pos; | |
139 char *p; | |
140 | |
141 /* | |
142 * set a byte in the positions array to indicate if a field or | |
143 * column is to be selected; use +1, it's 1-based, not 0-based. | |
144 * This parser is less restrictive than the Draft 9 POSIX spec. | |
145 * POSIX doesn't allow lists that aren't in increasing order or | |
146 * overlapping lists. We also handle "-3-5" although there's no | |
147 * real reason too. | |
148 */ | |
149 while ((p = strsep(&list, ", \t"))) { | |
150 setautostart = start = stop = 0; | |
151 if (*p == '-') { | |
152 ++p; | |
153 setautostart = 1; | |
154 } | |
155 if (isdigit(*p)) { | |
156 start = stop = strtol(p, &p, 10); | |
157 if (setautostart && start > autostart) | |
158 autostart = start; | |
159 } | |
160 if (*p == '-') { | |
161 if (isdigit(p[1])) | |
162 stop = strtol(p + 1, &p, 10); | |
163 if (*p == '-') { | |
164 ++p; | |
165 if (!autostop || autostop > stop) | |
166 autostop = stop; | |
167 } | |
168 } | |
169 if (*p) | |
170 errx(1, "[-cf] list: illegal list value"); | |
171 if (!stop || !start) | |
172 errx(1, "[-cf] list: values may not include zero"); | |
173 if (stop > _POSIX2_LINE_MAX) | |
174 errx(1, "[-cf] list: %d too large (max %d)", | |
175 stop, _POSIX2_LINE_MAX); | |
176 if (maxval < stop) | |
177 maxval = stop; | |
178 for (pos = positions + start; start++ <= stop; *pos++ = 1) | |
179 ; | |
180 } | |
181 | |
182 /* overlapping ranges */ | |
183 if (autostop && maxval > autostop) | |
184 maxval = autostop; | |
185 | |
186 /* set autostart */ | |
187 if (autostart) | |
188 memset(positions + 1, '1', autostart); | |
189 } | |
190 | |
191 /* ARGSUSED */ | |
192 void | |
193 c_cut(FILE *fp, char *fname) | |
194 { | |
195 int ch, col; | |
196 char *pos; | |
197 | |
198 for (;;) { | |
199 pos = positions + 1; | |
200 for (col = maxval; col; --col) { | |
201 if ((ch = getc(fp)) == EOF) | |
202 return; | |
203 if (ch == '\n') | |
204 break; | |
205 if (*pos++) | |
206 (void)putchar(ch); | |
207 } | |
208 if (ch != '\n') { | |
209 if (autostop) | |
210 while ((ch = getc(fp)) != EOF && ch != '\n') | |
211 (void)putchar(ch); | |
212 else | |
213 while ((ch = getc(fp)) != EOF && ch != '\n') | |
214 ; | |
215 } | |
216 (void)putchar('\n'); | |
217 } | |
218 } | |
219 | |
220 void | |
221 f_cut(FILE *fp, char *fname) | |
222 { | |
223 int ch, field, isdelim; | |
224 char *pos, *p, sep; | |
225 int output; | |
226 size_t len; | |
227 char *lbuf, *tbuf; | |
228 | |
229 for (sep = dchar, tbuf = NULL; (lbuf = fgetln(fp, &len));) { | |
230 output = 0; | |
231 if (lbuf[len - 1] != '\n') { | |
232 /* no newline at the end of the last line so add one */ | |
233 if ((tbuf = (char *)malloc(len + 1)) == NULL) | |
234 err(1, NULL); | |
235 memcpy(tbuf, lbuf, len); | |
236 tbuf[len] = '\n'; | |
237 lbuf = tbuf; | |
238 } | |
239 for (isdelim = 0, p = lbuf;; ++p) { | |
240 ch = *p; | |
241 /* this should work if newline is delimiter */ | |
242 if (ch == sep) | |
243 isdelim = 1; | |
244 if (ch == '\n') { | |
245 if (!isdelim && !sflag) | |
246 (void)fwrite(lbuf, len, 1, stdout); | |
247 break; | |
248 } | |
249 } | |
250 if (!isdelim) | |
251 continue; | |
252 | |
253 pos = positions + 1; | |
254 for (field = maxval, p = lbuf; field; --field, ++pos) { | |
255 if (*pos) { | |
256 if (output++) | |
257 (void)putchar(sep); | |
258 while ((ch = *p++) != '\n' && ch != sep) | |
259 (void)putchar(ch); | |
260 } else | |
261 while ((ch = *p++) != '\n' && ch != sep) | |
262 ; | |
263 if (ch == '\n') | |
264 break; | |
265 } | |
266 if (ch != '\n') { | |
267 if (autostop) { | |
268 if (output) | |
269 (void)putchar(sep); | |
270 for (; (ch = *p) != '\n'; ++p) | |
271 (void)putchar(ch); | |
272 } else | |
273 for (; (ch = *p) != '\n'; ++p) | |
274 ; | |
275 } | |
276 (void)putchar('\n'); | |
277 } | |
278 if (tbuf) | |
279 free(tbuf); | |
280 } | |
281 | |
282 void | |
283 usage(void) | |
284 { | |
285 (void)fprintf(stderr, | |
286 "usage: cut -b list [-n] [file ...]\n" | |
287 " cut -c list [file ...]\n" | |
288 " cut -f list [-s] [-d delim] [file ...]\n"); | |
289 exit(1); | |
290 } |