diff options
-rw-r--r-- | coreutils/libcoreutils/Makefile.in | 2 | ||||
-rw-r--r-- | coreutils/libcoreutils/xgetoptfile_sort_uniq.c | 38 | ||||
-rw-r--r-- | coreutils/uniq.c | 67 | ||||
-rw-r--r-- | include/usage.h | 2 | ||||
-rwxr-xr-x | testsuite/uniq.tests | 36 |
5 files changed, 74 insertions, 71 deletions
diff --git a/coreutils/libcoreutils/Makefile.in b/coreutils/libcoreutils/Makefile.in index 5f692b600..fe66c8243 100644 --- a/coreutils/libcoreutils/Makefile.in +++ b/coreutils/libcoreutils/Makefile.in | |||
@@ -23,7 +23,7 @@ LIBCOREUTILS_DIR:=$(top_builddir)/coreutils/libcoreutils/ | |||
23 | endif | 23 | endif |
24 | srcdir=$(top_srcdir)/coreutils/libcoreutils | 24 | srcdir=$(top_srcdir)/coreutils/libcoreutils |
25 | 25 | ||
26 | LIBCOREUTILS_SRC:= cp_mv_stat.c getopt_mk_fifo_nod.c xgetoptfile_sort_uniq.c | 26 | LIBCOREUTILS_SRC:= cp_mv_stat.c getopt_mk_fifo_nod.c |
27 | 27 | ||
28 | LIBCOREUTILS_OBJS=$(patsubst %.c,$(LIBCOREUTILS_DIR)%.o, $(LIBCOREUTILS_SRC)) | 28 | LIBCOREUTILS_OBJS=$(patsubst %.c,$(LIBCOREUTILS_DIR)%.o, $(LIBCOREUTILS_SRC)) |
29 | 29 | ||
diff --git a/coreutils/libcoreutils/xgetoptfile_sort_uniq.c b/coreutils/libcoreutils/xgetoptfile_sort_uniq.c deleted file mode 100644 index a63daf97b..000000000 --- a/coreutils/libcoreutils/xgetoptfile_sort_uniq.c +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * coreutils utility routine | ||
4 | * | ||
5 | * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <stdio.h> | ||
24 | #include <unistd.h> | ||
25 | #include "libbb.h" | ||
26 | #include "coreutils.h" | ||
27 | |||
28 | extern FILE *xgetoptfile_sort_uniq(char **argv, const char *mode) | ||
29 | { | ||
30 | const char *n; | ||
31 | |||
32 | if ((n = *argv) != NULL) { | ||
33 | if ((*n != '-') || n[1]) { | ||
34 | return bb_xfopen(n, mode); | ||
35 | } | ||
36 | } | ||
37 | return (*mode == 'r') ? stdin : stdout; | ||
38 | } | ||
diff --git a/coreutils/uniq.c b/coreutils/uniq.c index 312653263..aa26e0575 100644 --- a/coreutils/uniq.c +++ b/coreutils/uniq.c | |||
@@ -4,19 +4,7 @@ | |||
4 | * | 4 | * |
5 | * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> | 5 | * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * Licensed under GPL v2, see file LICENSE in this tarball for details. |
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | 8 | * |
21 | */ | 9 | */ |
22 | 10 | ||
@@ -31,7 +19,21 @@ | |||
31 | #include "busybox.h" | 19 | #include "busybox.h" |
32 | #include "libcoreutils/coreutils.h" | 20 | #include "libcoreutils/coreutils.h" |
33 | 21 | ||
34 | static const char uniq_opts[] = "f:s:cdu\0\7\3\5\1\2\4"; | 22 | /* The extra data is flags to make -d and -u switch each other off */ |
23 | static const char uniq_opts[] = "cudf:s:\0\7\3\5\1\2\4"; | ||
24 | |||
25 | #define SHOW_COUNT 1 | ||
26 | #define SHOW_UNIQUE 2 | ||
27 | #define SHOW_DUPLICATE 4 | ||
28 | |||
29 | static FILE *open_arg(char **argv, char *mode) | ||
30 | { | ||
31 | char *n=*argv; | ||
32 | |||
33 | return (n && *n != '-' && n[1]) ? bb_xfopen(n, mode) : | ||
34 | *mode=='r' ? stdin : stdout; | ||
35 | } | ||
36 | |||
35 | 37 | ||
36 | int uniq_main(int argc, char **argv) | 38 | int uniq_main(int argc, char **argv) |
37 | { | 39 | { |
@@ -39,28 +41,37 @@ int uniq_main(int argc, char **argv) | |||
39 | unsigned long dups, skip_fields, skip_chars, i; | 41 | unsigned long dups, skip_fields, skip_chars, i; |
40 | const char *oldline, *oldskipped, *line, *skipped, *input_filename; | 42 | const char *oldline, *oldskipped, *line, *skipped, *input_filename; |
41 | int opt; | 43 | int opt; |
42 | int uniq_flags = 6; /* -u */ | 44 | int uniq_flags = SHOW_UNIQUE | SHOW_DUPLICATE; |
43 | 45 | ||
44 | skip_fields = skip_chars = 0; | 46 | skip_fields = skip_chars = 0; |
45 | 47 | ||
46 | while ((opt = getopt(argc, argv, uniq_opts)) > 0) { | 48 | while ((opt = getopt(argc, argv, uniq_opts)) > 0) { |
47 | if (opt == 'f') skip_fields = bb_xgetularg10(optarg); | 49 | if (opt == 'f') skip_fields = bb_xgetularg10(optarg); |
48 | else if (opt == 's') skip_chars = bb_xgetularg10(optarg); | 50 | else if (opt == 's') skip_chars = bb_xgetularg10(optarg); |
51 | |||
52 | /* This bit uses the extra data at the end of uniq_opts to make | ||
53 | * -d and -u switch each other off in a very small amount of space */ | ||
54 | |||
49 | else if ((line = strchr(uniq_opts, opt)) != NULL) { | 55 | else if ((line = strchr(uniq_opts, opt)) != NULL) { |
50 | uniq_flags &= line[4]; | 56 | uniq_flags &= line[8]; |
51 | uniq_flags |= line[7]; | 57 | uniq_flags |= line[11]; |
52 | } else bb_show_usage(); | 58 | } else bb_show_usage(); |
53 | } | 59 | } |
54 | 60 | ||
55 | input_filename = *(argv += optind); | 61 | input_filename = *(argv += optind); |
56 | 62 | ||
57 | in = xgetoptfile_sort_uniq(argv, "r"); | 63 | in = open_arg(argv, "r"); |
58 | if (*argv) ++argv; | 64 | if (*argv) ++argv; |
59 | out = xgetoptfile_sort_uniq(argv, "w"); | 65 | out = open_arg(argv, "w"); |
60 | if (*argv && argv[1]) bb_show_usage(); | 66 | if (*argv && argv[1]) bb_show_usage(); |
61 | 67 | ||
62 | oldline = NULL; | 68 | line = skipped = NULL; |
63 | 69 | ||
70 | NOT_DUPLICATE: | ||
71 | oldline = line; | ||
72 | oldskipped = skipped; | ||
73 | dups = 0; | ||
74 | |||
64 | /* gnu uniq ignores newlines */ | 75 | /* gnu uniq ignores newlines */ |
65 | while ((line = bb_get_chomped_line_from_file(in)) != NULL) { | 76 | while ((line = bb_get_chomped_line_from_file(in)) != NULL) { |
66 | skipped = line; | 77 | skipped = line; |
@@ -70,27 +81,21 @@ int uniq_main(int argc, char **argv) | |||
70 | } | 81 | } |
71 | for (i = skip_chars ; *skipped && i ; i--) ++skipped; | 82 | for (i = skip_chars ; *skipped && i ; i--) ++skipped; |
72 | if (oldline) { | 83 | if (oldline) { |
73 | if (strcmp(oldskipped, skipped) == 0) { | 84 | if (!strcmp(oldskipped, skipped)) { |
74 | ++dups; /* Note: Testing for overflow seems excessive. */ | 85 | ++dups; /* Note: Testing for overflow seems excessive. */ |
75 | continue; | 86 | continue; |
76 | } | 87 | } |
77 | DO_LAST: | 88 | DO_LAST: |
78 | if ((dups && (uniq_flags & 2)) || (!dups && (uniq_flags & 4))) { | 89 | if (uniq_flags & (dups ? SHOW_DUPLICATE : SHOW_UNIQUE)) { |
79 | bb_fprintf(out, "\0%7d\t" + (uniq_flags & 1), dups + 1); | 90 | bb_fprintf(out, "\0%7d " + (uniq_flags & SHOW_COUNT), dups + 1); |
80 | bb_fprintf(out, "%s\n", oldline); | 91 | bb_fprintf(out, "%s\n", oldline); |
81 | } | 92 | } |
82 | free((void *)oldline); | 93 | free((void *)oldline); |
83 | } | 94 | } |
84 | 95 | goto NOT_DUPLICATE; | |
85 | oldline = line; | ||
86 | oldskipped = skipped; | ||
87 | dups = 0; | ||
88 | } | 96 | } |
89 | 97 | ||
90 | if (oldline) { | 98 | if (oldline) goto DO_LAST; |
91 | skipped = NULL; | ||
92 | goto DO_LAST; | ||
93 | } | ||
94 | 99 | ||
95 | bb_xferror(in, input_filename); | 100 | bb_xferror(in, input_filename); |
96 | 101 | ||
diff --git a/include/usage.h b/include/usage.h index 36d43cb39..29d78bbbb 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -3041,7 +3041,7 @@ | |||
3041 | "\t-f\tforce overwrite an existing file" | 3041 | "\t-f\tforce overwrite an existing file" |
3042 | 3042 | ||
3043 | #define uniq_trivial_usage \ | 3043 | #define uniq_trivial_usage \ |
3044 | "[OPTION]... [INPUT [OUTPUT]]" | 3044 | "[-fscdu]... [INPUT [OUTPUT]]" |
3045 | #define uniq_full_usage \ | 3045 | #define uniq_full_usage \ |
3046 | "Discard all but one of successive identical lines from INPUT\n" \ | 3046 | "Discard all but one of successive identical lines from INPUT\n" \ |
3047 | "(or standard input), writing to OUTPUT (or standard output).\n\n" \ | 3047 | "(or standard input), writing to OUTPUT (or standard output).\n\n" \ |
diff --git a/testsuite/uniq.tests b/testsuite/uniq.tests new file mode 100755 index 000000000..dc37d0a32 --- /dev/null +++ b/testsuite/uniq.tests | |||
@@ -0,0 +1,36 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | # SUSv3 compliant uniq tests. | ||
4 | # Copyright 2005 by Rob Landley <rob@landley.net> | ||
5 | # Licensed under GPL v2, see file LICENSE for details. | ||
6 | |||
7 | # AUDIT: Not full coverage of the spec yet. | ||
8 | |||
9 | if [ ${#COMMAND} -eq 0 ]; then COMMAND=uniq; fi | ||
10 | . testing.sh | ||
11 | |||
12 | # The basic tests. These should work even with the small busybox. | ||
13 | #-f skip fields | ||
14 | #-s skip chars | ||
15 | #-c occurrences | ||
16 | #-d dups only | ||
17 | #-u | ||
18 | testing "uniq (default to stdin)" "" "one\ntwo\nthree\n" "" \ | ||
19 | "one\ntwo\ntwo\nthree\nthree\nthree\n" | ||
20 | testing "uniq - (specify stdin)" "-" "one\ntwo\nthree\n" "" \ | ||
21 | "one\ntwo\ntwo\nthree\nthree\nthree\n" | ||
22 | testing "uniq input (specify file)" "input" "one\ntwo\nthree\n" \ | ||
23 | "one\ntwo\ntwo\nthree\nthree\nthree\n" "" | ||
24 | testing "uniq input outfile (two files)" "input actual > /dev/null" \ | ||
25 | "one\ntwo\nthree\n" "one\ntwo\ntwo\nthree\nthree\nthree\n" "" | ||
26 | #testing "uniq - outfile" "- outfile" "one\ntwo\nthree\n" \ | ||
27 | # "one\ntwo\ntwo\nthree\nthree\nthree\n" "" | ||
28 | |||
29 | testing "uniq -d" "-d" "two\nthree\n" "" \ | ||
30 | "one\ntwo\ntwo\nthree\nthree\nthree\n" | ||
31 | testing "uniq -c" "-c" " 1 one\n 2 two\n 3 three\n" "" \ | ||
32 | "one\ntwo\ntwo\nthree\nthree\nthree\n" | ||
33 | # testing "uniq -c -d" | ||
34 | # testing "uniq infile" | ||
35 | |||
36 | exit $FAILCOUNT | ||