aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coreutils/libcoreutils/Makefile.in2
-rw-r--r--coreutils/libcoreutils/xgetoptfile_sort_uniq.c38
-rw-r--r--coreutils/uniq.c67
-rw-r--r--include/usage.h2
-rwxr-xr-xtestsuite/uniq.tests36
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/
23endif 23endif
24srcdir=$(top_srcdir)/coreutils/libcoreutils 24srcdir=$(top_srcdir)/coreutils/libcoreutils
25 25
26LIBCOREUTILS_SRC:= cp_mv_stat.c getopt_mk_fifo_nod.c xgetoptfile_sort_uniq.c 26LIBCOREUTILS_SRC:= cp_mv_stat.c getopt_mk_fifo_nod.c
27 27
28LIBCOREUTILS_OBJS=$(patsubst %.c,$(LIBCOREUTILS_DIR)%.o, $(LIBCOREUTILS_SRC)) 28LIBCOREUTILS_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
28extern 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
34static 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 */
23static 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
29static 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
36int uniq_main(int argc, char **argv) 38int 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
70NOT_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 }
77DO_LAST: 88DO_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
9if [ ${#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
18testing "uniq (default to stdin)" "" "one\ntwo\nthree\n" "" \
19 "one\ntwo\ntwo\nthree\nthree\nthree\n"
20testing "uniq - (specify stdin)" "-" "one\ntwo\nthree\n" "" \
21 "one\ntwo\ntwo\nthree\nthree\nthree\n"
22testing "uniq input (specify file)" "input" "one\ntwo\nthree\n" \
23 "one\ntwo\ntwo\nthree\nthree\nthree\n" ""
24testing "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
29testing "uniq -d" "-d" "two\nthree\n" "" \
30 "one\ntwo\ntwo\nthree\nthree\nthree\n"
31testing "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
36exit $FAILCOUNT