aboutsummaryrefslogtreecommitdiff
path: root/coreutils/cut.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2003-06-20 09:01:58 +0000
committerEric Andersen <andersen@codepoet.org>2003-06-20 09:01:58 +0000
commit8876fb2f59a0b515b3121d5894933eef88ce566a (patch)
treef67de9320202043aca8ded20fb80d668c3b0c2d8 /coreutils/cut.c
parentdfce3536ace2bcd38bdd3731841998ce344d786e (diff)
downloadbusybox-w32-8876fb2f59a0b515b3121d5894933eef88ce566a.tar.gz
busybox-w32-8876fb2f59a0b515b3121d5894933eef88ce566a.tar.bz2
busybox-w32-8876fb2f59a0b515b3121d5894933eef88ce566a.zip
last_patch89 from vodz:
Manuel, I rewrite bb_getopt_ulflags() function for more universal usage. My version support now: - options with arguments (optional arg as GNU extension also) - complementaly and/or incomplementaly and/or incongruously and/or list options - long_opt (all applets may have long option, add supporting is trivial) This realisation full compatibile from your version. Code size grow 480 bytes, but only coreutils/* over compensate this size after using new function. Last patch reduced over 800 bytes and not full applied to all. "mkdir" and "mv" applets have long_opt now for demonstrate trivial addition support long_opt with usage new bb_getopt_ulflags(). Complementaly and/or incomplementaly and/or incongruously and/or list options logic is not trivial, but new "cut" and "grep" applets using this logic for examples with full demostrating. New "grep" applet reduced over 300 bytes. Mark, Also. I removed bug from "grep" applet. $ echo a b | busybox grep -e a b a b a b But right is printing one only. --w vodz
Diffstat (limited to 'coreutils/cut.c')
-rw-r--r--coreutils/cut.c68
1 files changed, 28 insertions, 40 deletions
diff --git a/coreutils/cut.c b/coreutils/cut.c
index c24cf6611..8ae762fb3 100644
--- a/coreutils/cut.c
+++ b/coreutils/cut.c
@@ -22,20 +22,22 @@
22 22
23#include <stdio.h> 23#include <stdio.h>
24#include <stdlib.h> 24#include <stdlib.h>
25#include <unistd.h> /* getopt */ 25#include <getopt.h>
26#include <unistd.h>
26#include <string.h> 27#include <string.h>
27#include <limits.h> 28#include <limits.h>
28#include "busybox.h" 29#include "busybox.h"
29 30
30 31
31/* globals from other files */
32extern int optind;
33extern char *optarg;
34
35
36/* option vars */ 32/* option vars */
37static char part = 0; /* (b)yte, (c)har, (f)ields */ 33static const char optstring[] = "b:c:f:d:sn";
38static unsigned int supress_non_delimited_lines = 0; 34#define OPT_BYTE_FLGS 1
35#define OPT_CHAR_FLGS 2
36#define OPT_FIELDS_FLGS 4
37#define OPT_DELIM_FLGS 8
38#define OPT_SUPRESS_FLGS 16
39static char part; /* (b)yte, (c)har, (f)ields */
40static unsigned int supress_non_delimited_lines;
39static char delim = '\t'; /* delimiter, default is tab */ 41static char delim = '\t'; /* delimiter, default is tab */
40 42
41struct cut_list { 43struct cut_list {
@@ -270,11 +272,11 @@ static void cut_file(FILE *file)
270 while ((line = bb_get_chomped_line_from_file(file)) != NULL) { 272 while ((line = bb_get_chomped_line_from_file(file)) != NULL) {
271 273
272 /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ 274 /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */
273 if (part == 'c' || part == 'b') 275 if ((part & (OPT_CHAR_FLGS | OPT_BYTE_FLGS)))
274 cut_line_by_chars(line); 276 cut_line_by_chars(line);
275 277
276 /* cut based on fields */ 278 /* cut based on fields */
277 else if (part == 'f') { 279 else {
278 if (delim == '\n') 280 if (delim == '\n')
279 cut_file_by_lines(line, linenum); 281 cut_file_by_lines(line, linenum);
280 else 282 else
@@ -289,46 +291,32 @@ static void cut_file(FILE *file)
289 291
290extern int cut_main(int argc, char **argv) 292extern int cut_main(int argc, char **argv)
291{ 293{
292 int opt; 294 unsigned long opt;
293 295 char *sopt, *sdopt;
294 while ((opt = getopt(argc, argv, "b:c:d:f:ns")) > 0) { 296
295 switch (opt) { 297 bb_opt_complementaly = "b~bcf:c~bcf:f~bcf";
296 case 'b': 298 opt = bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &sdopt);
297 case 'c': 299 part = opt & (OPT_BYTE_FLGS|OPT_CHAR_FLGS|OPT_FIELDS_FLGS);
298 case 'f': 300 if(part == 0)
299 /* make sure they didn't ask for two types of lists */ 301 bb_error_msg_and_die("you must specify a list of bytes, characters, or fields");
300 if (part != 0) { 302 if(opt & 0x80000000UL)
301 bb_error_msg_and_die("only one type of list may be specified"); 303 bb_error_msg_and_die("only one type of list may be specified");
302 } 304 parse_lists(sopt);
303 part = (char)opt; 305 if((opt & (OPT_DELIM_FLGS))) {
304 parse_lists(optarg); 306 if (strlen(sdopt) > 1) {
305 break;
306 case 'd':
307 if (strlen(optarg) > 1) {
308 bb_error_msg_and_die("the delimiter must be a single character"); 307 bb_error_msg_and_die("the delimiter must be a single character");
309 } 308 }
310 delim = optarg[0]; 309 delim = sdopt[0];
311 break;
312 case 'n':
313 /* no-op */
314 break;
315 case 's':
316 supress_non_delimited_lines++;
317 break;
318 }
319 }
320
321 if (part == 0) {
322 bb_error_msg_and_die("you must specify a list of bytes, characters, or fields");
323 } 310 }
311 supress_non_delimited_lines = opt & OPT_SUPRESS_FLGS;
324 312
325 /* non-field (char or byte) cutting has some special handling */ 313 /* non-field (char or byte) cutting has some special handling */
326 if (part != 'f') { 314 if (part != OPT_FIELDS_FLGS) {
327 if (supress_non_delimited_lines) { 315 if (supress_non_delimited_lines) {
328 bb_error_msg_and_die("suppressing non-delimited lines makes sense" 316 bb_error_msg_and_die("suppressing non-delimited lines makes sense"
329 " only when operating on fields"); 317 " only when operating on fields");
330 } 318 }
331 if (delim != '\t' && part != 'f') { 319 if (delim != '\t') {
332 bb_error_msg_and_die("a delimiter may be specified only when operating on fields"); 320 bb_error_msg_and_die("a delimiter may be specified only when operating on fields");
333 } 321 }
334 } 322 }