diff options
author | aldot <aldot@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-08-28 23:31:54 +0000 |
---|---|---|
committer | aldot <aldot@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-08-28 23:31:54 +0000 |
commit | d52f45a484fc7fc049ab40db9adc6ead7ea9b122 (patch) | |
tree | 2a57564b8917a983365c765d4daa83032d9f0a17 /coreutils/cut.c | |
parent | 2803d256e9decd450b955c2846bf945db72bb79e (diff) | |
download | busybox-w32-d52f45a484fc7fc049ab40db9adc6ead7ea9b122.tar.gz busybox-w32-d52f45a484fc7fc049ab40db9adc6ead7ea9b122.tar.bz2 busybox-w32-d52f45a484fc7fc049ab40db9adc6ead7ea9b122.zip |
- pull from busybox_scratch: r15829:15850
Various fixes, cleanups and shrinkage:
saves 952 Bytes:
text data bss dec hex filename
1087742 15853 790632 1894227 1ce753 ../busybox/busybox.old
1086790 15853 790632 1893275 1ce39b busybox
via:
# scripts/bloat-o-meter ../busybox/busybox_unstripped.old busybox_unstripped
function old new delta
ipcrm_main 756 822 +66
getval - 61 +61
maybe_set_utc - 40 +40
udhcpc_main 2896 2912 +16
md5_hash_block 428 437 +9
opt 8 16 +8
qgravechar 106 110 +4
make_bitmap 292 295 +3
inflate_unzip 2056 2059 +3
add_partition 1412 1414 +2
__parsespent 156 158 +2
qrealloc 41 42 +1
format - 1 +1
catv_main 313 314 +1
watch_main 293 292 -1
varunset 81 80 -1
part 1 - -1
check_if_skip 837 836 -1
start_stop_daemon_main 840 837 -3
create_lost_and_found 175 172 -3
supress_non_delimited_lines 4 - -4
static.l 4 - -4
static.c 5 1 -4
bsd_sum_file 237 233 -4
eval2 338 332 -6
arithmetic_common 166 158 -8
cmpfunc 22 5 -17
cksum_main 294 275 -19
cmp_main 465 439 -26
dd_main 1535 1508 -27
rmmod_main 376 333 -43
cut_file 727 644 -83
ipcs_main 3809 3721 -88
cut_main 722 614 -108
date_main 1443 1263 -180
remove_ids 222 - -222
------------------------------------------------------------------------------
(add/remove: 3/4 grow/shrink: 11/18 up/down: 217/-853) Total: -636 bytes
git-svn-id: svn://busybox.net/trunk/busybox@16009 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'coreutils/cut.c')
-rw-r--r-- | coreutils/cut.c | 479 |
1 files changed, 224 insertions, 255 deletions
diff --git a/coreutils/cut.c b/coreutils/cut.c index 1b80e7e73..d88a891b0 100644 --- a/coreutils/cut.c +++ b/coreutils/cut.c | |||
@@ -4,28 +4,24 @@ | |||
4 | * | 4 | * |
5 | * Copyright (C) 1999,2000,2001 by Lineo, inc. | 5 | * Copyright (C) 1999,2000,2001 by Lineo, inc. |
6 | * Written by Mark Whitley <markw@codepoet.org> | 6 | * Written by Mark Whitley <markw@codepoet.org> |
7 | * debloated by Bernhard Fischer | ||
7 | * | 8 | * |
8 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 9 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
9 | */ | 10 | */ |
10 | 11 | ||
11 | #include <stdio.h> | ||
12 | #include <stdlib.h> | ||
13 | #include <unistd.h> | ||
14 | #include <string.h> | ||
15 | #include <limits.h> | ||
16 | #include "busybox.h" | 12 | #include "busybox.h" |
17 | 13 | ||
18 | |||
19 | /* option vars */ | 14 | /* option vars */ |
20 | static const char optstring[] = "b:c:f:d:sn"; | 15 | static const char *const optstring = "b:c:f:d:sn"; |
21 | #define OPT_BYTE_FLGS 1 | 16 | |
22 | #define OPT_CHAR_FLGS 2 | 17 | #define CUT_OPT_BYTE_FLGS (1<<0) |
23 | #define OPT_FIELDS_FLGS 4 | 18 | #define CUT_OPT_CHAR_FLGS (1<<1) |
24 | #define OPT_DELIM_FLGS 8 | 19 | #define CUT_OPT_FIELDS_FLGS (1<<2) |
25 | #define OPT_SUPRESS_FLGS 16 | 20 | #define CUT_OPT_DELIM_FLGS (1<<3) |
26 | static char part; /* (b)yte, (c)har, (f)ields */ | 21 | #define CUT_OPT_SUPPRESS_FLGS (1<<4) |
27 | static unsigned int supress_non_delimited_lines; | 22 | static unsigned long opt; |
28 | static char delim = '\t'; /* delimiter, default is tab */ | 23 | |
24 | static char delim = '\t'; /* delimiter, default is tab */ | ||
29 | 25 | ||
30 | struct cut_list { | 26 | struct cut_list { |
31 | int startpos; | 27 | int startpos; |
@@ -38,295 +34,268 @@ enum { | |||
38 | NON_RANGE = -1 | 34 | NON_RANGE = -1 |
39 | }; | 35 | }; |
40 | 36 | ||
41 | static struct cut_list *cut_lists = NULL; /* growable array holding a series of lists */ | 37 | /* growable array holding a series of lists */ |
42 | static unsigned int nlists = 0; /* number of elements in above list */ | 38 | static struct cut_list *cut_lists; |
39 | static unsigned int nlists; /* number of elements in above list */ | ||
43 | 40 | ||
44 | 41 | ||
45 | static int cmpfunc(const void *a, const void *b) | 42 | static int cmpfunc(const void *a, const void *b) |
46 | { | 43 | { |
47 | struct cut_list *la = (struct cut_list *)a; | 44 | return (((struct cut_list *) a)->startpos - |
48 | struct cut_list *lb = (struct cut_list *)b; | 45 | ((struct cut_list *) b)->startpos); |
49 | |||
50 | if (la->startpos > lb->startpos) | ||
51 | return 1; | ||
52 | if (la->startpos < lb->startpos) | ||
53 | return -1; | ||
54 | return 0; | ||
55 | } | ||
56 | 46 | ||
47 | } | ||
57 | 48 | ||
58 | /* | 49 | static void cut_file(FILE * file) |
59 | * parse_lists() - parses a list and puts values into startpos and endpos. | ||
60 | * valid list formats: N, N-, N-M, -M | ||
61 | * more than one list can be separated by commas | ||
62 | */ | ||
63 | static void parse_lists(char *lists) | ||
64 | { | 50 | { |
65 | char *ltok = NULL; | 51 | char *line = NULL; |
66 | char *ntok = NULL; | 52 | unsigned int linenum = 0; /* keep these zero-based to be consistent */ |
67 | char *junk; | ||
68 | int s = 0, e = 0; | ||
69 | |||
70 | /* take apart the lists, one by one (they are separated with commas */ | ||
71 | while ((ltok = strsep(&lists, ",")) != NULL) { | ||
72 | |||
73 | /* it's actually legal to pass an empty list */ | ||
74 | if (strlen(ltok) == 0) | ||
75 | continue; | ||
76 | |||
77 | /* get the start pos */ | ||
78 | ntok = strsep(<ok, "-"); | ||
79 | if (ntok == NULL) { | ||
80 | fprintf(stderr, "Help ntok is null for starting position! What do I do?\n"); | ||
81 | } else if (strlen(ntok) == 0) { | ||
82 | s = BOL; | ||
83 | } else { | ||
84 | s = strtoul(ntok, &junk, 10); | ||
85 | if(*junk != '\0' || s < 0) | ||
86 | bb_error_msg_and_die("invalid byte or field list"); | ||
87 | |||
88 | /* account for the fact that arrays are zero based, while the user | ||
89 | * expects the first char on the line to be char # 1 */ | ||
90 | if (s != 0) | ||
91 | s--; | ||
92 | } | ||
93 | |||
94 | /* get the end pos */ | ||
95 | ntok = strsep(<ok, "-"); | ||
96 | if (ntok == NULL) { | ||
97 | e = NON_RANGE; | ||
98 | } else if (strlen(ntok) == 0) { | ||
99 | e = EOL; | ||
100 | } else { | ||
101 | e = strtoul(ntok, &junk, 10); | ||
102 | if(*junk != '\0' || e < 0) | ||
103 | bb_error_msg_and_die("invalid byte or field list"); | ||
104 | /* if the user specified and end position of 0, that means "til the | ||
105 | * end of the line */ | ||
106 | if (e == 0) | ||
107 | e = INT_MAX; | ||
108 | e--; /* again, arrays are zero based, lines are 1 based */ | ||
109 | if (e == s) | ||
110 | e = NON_RANGE; | ||
111 | } | ||
112 | |||
113 | /* if there's something left to tokenize, the user past an invalid list */ | ||
114 | if (ltok) | ||
115 | bb_error_msg_and_die("invalid byte or field list"); | ||
116 | |||
117 | /* add the new list */ | ||
118 | cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists)); | ||
119 | cut_lists[nlists-1].startpos = s; | ||
120 | cut_lists[nlists-1].endpos = e; | ||
121 | } | ||
122 | |||
123 | /* make sure we got some cut positions out of all that */ | ||
124 | if (nlists == 0) | ||
125 | bb_error_msg_and_die("missing list of positions"); | ||
126 | |||
127 | /* now that the lists are parsed, we need to sort them to make life easier | ||
128 | * on us when it comes time to print the chars / fields / lines */ | ||
129 | qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc); | ||
130 | 53 | ||
131 | } | 54 | /* go through every line in the file */ |
55 | while ((line = bb_get_chomped_line_from_file(file)) != NULL) { | ||
132 | 56 | ||
57 | /* set up a list so we can keep track of what's been printed */ | ||
58 | char * printed = xzalloc(strlen(line) * sizeof(char)); | ||
59 | char * orig_line = line; | ||
60 | unsigned int cl_pos = 0; | ||
61 | int spos; | ||
133 | 62 | ||
134 | static void cut_line_by_chars(const char *line) | 63 | /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ |
135 | { | 64 | if ((opt & (CUT_OPT_CHAR_FLGS | CUT_OPT_BYTE_FLGS))) { |
136 | int c, l; | 65 | /* print the chars specified in each cut list */ |
137 | /* set up a list so we can keep track of what's been printed */ | 66 | for (; cl_pos < nlists; cl_pos++) { |
138 | char *printed = xzalloc(strlen(line)); | 67 | spos = cut_lists[cl_pos].startpos; |
139 | 68 | while (spos < strlen(line)) { | |
140 | /* print the chars specified in each cut list */ | 69 | if (!printed[spos]) { |
141 | for (c = 0; c < nlists; c++) { | 70 | printed[spos] = 'X'; |
142 | l = cut_lists[c].startpos; | 71 | putchar(line[spos]); |
143 | while (l < strlen(line)) { | 72 | } |
144 | if (!printed[l]) { | 73 | spos++; |
145 | putchar(line[l]); | 74 | if (spos > cut_lists[cl_pos].endpos |
146 | printed[l] = 'X'; | 75 | || cut_lists[cl_pos].endpos == NON_RANGE) |
76 | break; | ||
77 | } | ||
78 | } | ||
79 | } else if (delim == '\n') { /* cut by lines */ | ||
80 | spos = cut_lists[cl_pos].startpos; | ||
81 | |||
82 | /* get out if we have no more lists to process or if the lines | ||
83 | * are lower than what we're interested in */ | ||
84 | if (linenum < spos || cl_pos >= nlists) | ||
85 | goto next_line; | ||
86 | |||
87 | /* if the line we're looking for is lower than the one we were | ||
88 | * passed, it means we displayed it already, so move on */ | ||
89 | while (spos < linenum) { | ||
90 | spos++; | ||
91 | /* go to the next list if we're at the end of this one */ | ||
92 | if (spos > cut_lists[cl_pos].endpos | ||
93 | || cut_lists[cl_pos].endpos == NON_RANGE) { | ||
94 | cl_pos++; | ||
95 | /* get out if there's no more lists to process */ | ||
96 | if (cl_pos >= nlists) | ||
97 | goto next_line; | ||
98 | spos = cut_lists[cl_pos].startpos; | ||
99 | /* get out if the current line is lower than the one | ||
100 | * we just became interested in */ | ||
101 | if (linenum < spos) | ||
102 | goto next_line; | ||
103 | } | ||
147 | } | 104 | } |
148 | l++; | ||
149 | if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos) | ||
150 | break; | ||
151 | } | ||
152 | } | ||
153 | putchar('\n'); /* cuz we were handed a chomped line */ | ||
154 | free(printed); | ||
155 | } | ||
156 | |||
157 | 105 | ||
158 | static void cut_line_by_fields(char *line) | 106 | /* If we made it here, it means we've found the line we're |
159 | { | 107 | * looking for, so print it */ |
160 | int c, f; | ||
161 | int ndelim = -1; /* zero-based / one-based problem */ | ||
162 | int nfields_printed = 0; | ||
163 | char *field = NULL; | ||
164 | char d[2] = { delim, 0 }; | ||
165 | char *printed; | ||
166 | |||
167 | /* test the easy case first: does this line contain any delimiters? */ | ||
168 | if (strchr(line, delim) == NULL) { | ||
169 | if (!supress_non_delimited_lines) | ||
170 | puts(line); | 108 | puts(line); |
171 | return; | 109 | goto next_line; |
172 | } | 110 | } else { /* cut by fields */ |
173 | 111 | int ndelim = -1; /* zero-based / one-based problem */ | |
174 | /* set up a list so we can keep track of what's been printed */ | 112 | int nfields_printed = 0; |
175 | printed = xzalloc(strlen(line)); | 113 | char *field = NULL; |
176 | 114 | const char delimiter[2] = { delim, 0 }; | |
177 | /* process each list on this line, for as long as we've got a line to process */ | 115 | |
178 | for (c = 0; c < nlists && line; c++) { | 116 | /* does this line contain any delimiters? */ |
179 | f = cut_lists[c].startpos; | 117 | if (strchr(line, delim) == NULL) { |
180 | do { | 118 | if (!(opt & CUT_OPT_SUPPRESS_FLGS)) |
181 | 119 | puts(line); | |
182 | /* find the field we're looking for */ | 120 | goto next_line; |
183 | while (line && ndelim < f) { | ||
184 | field = strsep(&line, d); | ||
185 | ndelim++; | ||
186 | } | 121 | } |
187 | 122 | ||
188 | /* we found it, and it hasn't been printed yet */ | 123 | /* process each list on this line, for as long as we've got |
189 | if (field && ndelim == f && !printed[ndelim]) { | 124 | * a line to process */ |
190 | /* if this isn't our first time through, we need to print the | 125 | for (; cl_pos < nlists && line; cl_pos++) { |
191 | * delimiter after the last field that was printed */ | 126 | spos = cut_lists[cl_pos].startpos; |
192 | if (nfields_printed > 0) | 127 | do { |
193 | putchar(delim); | 128 | |
194 | fputs(field, stdout); | 129 | /* find the field we're looking for */ |
195 | printed[ndelim] = 'X'; | 130 | while (line && ndelim < spos) { |
196 | nfields_printed++; | 131 | field = strsep(&line, delimiter); |
132 | ndelim++; | ||
133 | } | ||
134 | |||
135 | /* we found it, and it hasn't been printed yet */ | ||
136 | if (field && ndelim == spos && !printed[ndelim]) { | ||
137 | /* if this isn't our first time through, we need to | ||
138 | * print the delimiter after the last field that was | ||
139 | * printed */ | ||
140 | if (nfields_printed > 0) | ||
141 | putchar(delim); | ||
142 | fputs(field, stdout); | ||
143 | printed[ndelim] = 'X'; | ||
144 | nfields_printed++; /* shouldn't overflow.. */ | ||
145 | } | ||
146 | |||
147 | spos++; | ||
148 | |||
149 | /* keep going as long as we have a line to work with, | ||
150 | * this is a list, and we're not at the end of that | ||
151 | * list */ | ||
152 | } while (spos <= cut_lists[cl_pos].endpos && line | ||
153 | && cut_lists[cl_pos].endpos != NON_RANGE); | ||
197 | } | 154 | } |
198 | |||
199 | f++; | ||
200 | |||
201 | /* keep going as long as we have a line to work with, this is a | ||
202 | * list, and we're not at the end of that list */ | ||
203 | } while (line && cut_lists[c].endpos != NON_RANGE && f <= cut_lists[c].endpos); | ||
204 | } | ||
205 | |||
206 | /* if we printed anything at all, we need to finish it with a newline cuz | ||
207 | * we were handed a chomped line */ | ||
208 | putchar('\n'); | ||
209 | |||
210 | free(printed); | ||
211 | } | ||
212 | |||
213 | |||
214 | static void cut_file_by_lines(const char *line, unsigned int linenum) | ||
215 | { | ||
216 | static int c = 0; | ||
217 | static int l = -1; | ||
218 | |||
219 | /* I can't initialize this above cuz the "initializer isn't | ||
220 | * constant" *sigh* */ | ||
221 | if (l == -1) | ||
222 | l = cut_lists[c].startpos; | ||
223 | |||
224 | /* get out if we have no more lists to process or if the lines are lower | ||
225 | * than what we're interested in */ | ||
226 | if (c >= nlists || linenum < l) | ||
227 | return; | ||
228 | |||
229 | /* if the line we're looking for is lower than the one we were passed, it | ||
230 | * means we displayed it already, so move on */ | ||
231 | while (l < linenum) { | ||
232 | l++; | ||
233 | /* move on to the next list if we're at the end of this one */ | ||
234 | if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos) { | ||
235 | c++; | ||
236 | /* get out if there's no more lists to process */ | ||
237 | if (c >= nlists) | ||
238 | return; | ||
239 | l = cut_lists[c].startpos; | ||
240 | /* get out if the current line is lower than the one we just became | ||
241 | * interested in */ | ||
242 | if (linenum < l) | ||
243 | return; | ||
244 | } | 155 | } |
156 | /* if we printed anything at all, we need to finish it with a | ||
157 | * newline cuz we were handed a chomped line */ | ||
158 | putchar('\n'); | ||
159 | next_line: | ||
160 | linenum++; | ||
161 | free(printed); | ||
162 | free(orig_line); | ||
245 | } | 163 | } |
246 | |||
247 | /* If we made it here, it means we've found the line we're looking for, so print it */ | ||
248 | puts(line); | ||
249 | } | 164 | } |
250 | 165 | ||
251 | 166 | static int getval(char *ntok) | |
252 | /* | ||
253 | * snippy-snip | ||
254 | */ | ||
255 | static void cut_file(FILE *file) | ||
256 | { | 167 | { |
257 | char *line = NULL; | 168 | char *junk; |
258 | unsigned int linenum = 0; /* keep these zero-based to be consistent */ | 169 | int i = strtoul(ntok, &junk, 10); |
259 | |||
260 | /* go through every line in the file */ | ||
261 | while ((line = bb_get_chomped_line_from_file(file)) != NULL) { | ||
262 | |||
263 | /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ | ||
264 | if ((part & (OPT_CHAR_FLGS | OPT_BYTE_FLGS))) | ||
265 | cut_line_by_chars(line); | ||
266 | |||
267 | /* cut based on fields */ | ||
268 | else { | ||
269 | if (delim == '\n') | ||
270 | cut_file_by_lines(line, linenum); | ||
271 | else | ||
272 | cut_line_by_fields(line); | ||
273 | } | ||
274 | 170 | ||
275 | linenum++; | 171 | if (*junk != '\0' || i < 0) |
276 | free(line); | 172 | bb_error_msg_and_die("invalid byte or field list"); |
277 | } | 173 | return i; |
278 | } | 174 | } |
279 | 175 | ||
176 | static const char * const _op_on_field = " only when operating on fields"; | ||
280 | 177 | ||
281 | int cut_main(int argc, char **argv) | 178 | int cut_main(int argc, char **argv) |
282 | { | 179 | { |
283 | unsigned long opt; | 180 | char *sopt, *ltok; |
284 | char *sopt, *sdopt; | ||
285 | 181 | ||
286 | bb_opt_complementally = "b--bcf:c--bcf:f--bcf"; | 182 | bb_opt_complementally = "b--bcf:c--bcf:f--bcf"; |
287 | opt = bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &sdopt); | 183 | opt = |
288 | part = opt & (OPT_BYTE_FLGS|OPT_CHAR_FLGS|OPT_FIELDS_FLGS); | 184 | bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, <ok); |
289 | if(part == 0) | 185 | if (!(opt & (CUT_OPT_BYTE_FLGS | CUT_OPT_CHAR_FLGS | CUT_OPT_FIELDS_FLGS))) |
290 | bb_error_msg_and_die("you must specify a list of bytes, characters, or fields"); | 186 | bb_error_msg_and_die |
291 | if(opt & BB_GETOPT_ERROR) | 187 | ("expected a list of bytes, characters, or fields"); |
188 | if (opt & BB_GETOPT_ERROR) | ||
292 | bb_error_msg_and_die("only one type of list may be specified"); | 189 | bb_error_msg_and_die("only one type of list may be specified"); |
293 | parse_lists(sopt); | 190 | |
294 | if((opt & (OPT_DELIM_FLGS))) { | 191 | if ((opt & (CUT_OPT_DELIM_FLGS))) { |
295 | if (strlen(sdopt) > 1) { | 192 | if (strlen(ltok) > 1) { |
296 | bb_error_msg_and_die("the delimiter must be a single character"); | 193 | bb_error_msg_and_die("the delimiter must be a single character"); |
297 | } | 194 | } |
298 | delim = sdopt[0]; | 195 | delim = ltok[0]; |
299 | } | 196 | } |
300 | supress_non_delimited_lines = opt & OPT_SUPRESS_FLGS; | ||
301 | 197 | ||
302 | /* non-field (char or byte) cutting has some special handling */ | 198 | /* non-field (char or byte) cutting has some special handling */ |
303 | if (part != OPT_FIELDS_FLGS) { | 199 | if (!(opt & CUT_OPT_FIELDS_FLGS)) { |
304 | if (supress_non_delimited_lines) { | 200 | if (opt & CUT_OPT_SUPPRESS_FLGS) { |
305 | bb_error_msg_and_die("suppressing non-delimited lines makes sense" | 201 | bb_error_msg_and_die |
306 | " only when operating on fields"); | 202 | ("suppressing non-delimited lines makes sense%s", |
203 | _op_on_field); | ||
307 | } | 204 | } |
308 | if (delim != '\t') { | 205 | if (delim != '\t') { |
309 | bb_error_msg_and_die("a delimiter may be specified only when operating on fields"); | 206 | bb_error_msg_and_die |
207 | ("a delimiter may be specified%s", _op_on_field); | ||
310 | } | 208 | } |
311 | } | 209 | } |
312 | 210 | ||
211 | /* | ||
212 | * parse list and put values into startpos and endpos. | ||
213 | * valid list formats: N, N-, N-M, -M | ||
214 | * more than one list can be separated by commas | ||
215 | */ | ||
216 | { | ||
217 | char *ntok; | ||
218 | int s = 0, e = 0; | ||
219 | |||
220 | /* take apart the lists, one by one (they are separated with commas */ | ||
221 | while ((ltok = strsep(&sopt, ",")) != NULL) { | ||
222 | |||
223 | /* it's actually legal to pass an empty list */ | ||
224 | if (strlen(ltok) == 0) | ||
225 | continue; | ||
226 | |||
227 | /* get the start pos */ | ||
228 | ntok = strsep(<ok, "-"); | ||
229 | if (ntok == NULL) { | ||
230 | bb_error_msg | ||
231 | ("internal error: ntok is null for start pos!?\n"); | ||
232 | } else if (strlen(ntok) == 0) { | ||
233 | s = BOL; | ||
234 | } else { | ||
235 | s = getval(ntok); | ||
236 | /* account for the fact that arrays are zero based, while | ||
237 | * the user expects the first char on the line to be char #1 */ | ||
238 | if (s != 0) | ||
239 | s--; | ||
240 | } | ||
241 | |||
242 | /* get the end pos */ | ||
243 | ntok = strsep(<ok, "-"); | ||
244 | if (ntok == NULL) { | ||
245 | e = NON_RANGE; | ||
246 | } else if (strlen(ntok) == 0) { | ||
247 | e = EOL; | ||
248 | } else { | ||
249 | e = getval(ntok); | ||
250 | /* if the user specified and end position of 0, that means "til the | ||
251 | * end of the line */ | ||
252 | if (e == 0) | ||
253 | e = EOL; | ||
254 | e--; /* again, arrays are zero based, lines are 1 based */ | ||
255 | if (e == s) | ||
256 | e = NON_RANGE; | ||
257 | } | ||
258 | |||
259 | /* if there's something left to tokenize, the user passed | ||
260 | * an invalid list */ | ||
261 | if (ltok) | ||
262 | bb_error_msg_and_die("invalid byte or field list"); | ||
263 | |||
264 | /* add the new list */ | ||
265 | cut_lists = | ||
266 | xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists)); | ||
267 | cut_lists[nlists - 1].startpos = s; | ||
268 | cut_lists[nlists - 1].endpos = e; | ||
269 | } | ||
270 | |||
271 | /* make sure we got some cut positions out of all that */ | ||
272 | if (nlists == 0) | ||
273 | bb_error_msg_and_die("missing list of positions"); | ||
274 | |||
275 | /* now that the lists are parsed, we need to sort them to make life | ||
276 | * easier on us when it comes time to print the chars / fields / lines | ||
277 | */ | ||
278 | qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc); | ||
279 | } | ||
280 | |||
313 | /* argv[(optind)..(argc-1)] should be names of file to process. If no | 281 | /* argv[(optind)..(argc-1)] should be names of file to process. If no |
314 | * files were specified or '-' was specified, take input from stdin. | 282 | * files were specified or '-' was specified, take input from stdin. |
315 | * Otherwise, we process all the files specified. */ | 283 | * Otherwise, we process all the files specified. */ |
316 | if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { | 284 | if (argv[optind] == NULL |
285 | || (argv[optind][0] == '-' && argv[optind][1] == '\0')) { | ||
317 | cut_file(stdin); | 286 | cut_file(stdin); |
318 | } | 287 | } else { |
319 | else { | ||
320 | int i; | ||
321 | FILE *file; | 288 | FILE *file; |
322 | for (i = optind; i < argc; i++) { | 289 | |
323 | file = bb_wfopen(argv[i], "r"); | 290 | for (; optind < argc; optind++) { |
324 | if(file) { | 291 | file = bb_wfopen(argv[optind], "r"); |
292 | if (file) { | ||
325 | cut_file(file); | 293 | cut_file(file); |
326 | fclose(file); | 294 | fclose(file); |
327 | } | 295 | } |
328 | } | 296 | } |
329 | } | 297 | } |
330 | 298 | if (ENABLE_FEATURE_CLEAN_UP) | |
299 | free(cut_lists); | ||
331 | return EXIT_SUCCESS; | 300 | return EXIT_SUCCESS; |
332 | } | 301 | } |