diff options
Diffstat (limited to 'coreutils/uniq.c')
-rw-r--r-- | coreutils/uniq.c | 67 |
1 files changed, 36 insertions, 31 deletions
diff --git a/coreutils/uniq.c b/coreutils/uniq.c index 3126532..aa26e05 100644 --- a/coreutils/uniq.c +++ b/coreutils/uniq.c @@ -4,19 +4,7 @@ * * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Licensed under GPL v2, see file LICENSE in this tarball for details. * */ @@ -31,7 +19,21 @@ #include "busybox.h" #include "libcoreutils/coreutils.h" -static const char uniq_opts[] = "f:s:cdu\0\7\3\5\1\2\4"; +/* The extra data is flags to make -d and -u switch each other off */ +static const char uniq_opts[] = "cudf:s:\0\7\3\5\1\2\4"; + +#define SHOW_COUNT 1 +#define SHOW_UNIQUE 2 +#define SHOW_DUPLICATE 4 + +static FILE *open_arg(char **argv, char *mode) +{ + char *n=*argv; + + return (n && *n != '-' && n[1]) ? bb_xfopen(n, mode) : + *mode=='r' ? stdin : stdout; +} + int uniq_main(int argc, char **argv) { @@ -39,28 +41,37 @@ int uniq_main(int argc, char **argv) unsigned long dups, skip_fields, skip_chars, i; const char *oldline, *oldskipped, *line, *skipped, *input_filename; int opt; - int uniq_flags = 6; /* -u */ + int uniq_flags = SHOW_UNIQUE | SHOW_DUPLICATE; skip_fields = skip_chars = 0; while ((opt = getopt(argc, argv, uniq_opts)) > 0) { if (opt == 'f') skip_fields = bb_xgetularg10(optarg); else if (opt == 's') skip_chars = bb_xgetularg10(optarg); + + /* This bit uses the extra data at the end of uniq_opts to make + * -d and -u switch each other off in a very small amount of space */ + else if ((line = strchr(uniq_opts, opt)) != NULL) { - uniq_flags &= line[4]; - uniq_flags |= line[7]; + uniq_flags &= line[8]; + uniq_flags |= line[11]; } else bb_show_usage(); } input_filename = *(argv += optind); - in = xgetoptfile_sort_uniq(argv, "r"); + in = open_arg(argv, "r"); if (*argv) ++argv; - out = xgetoptfile_sort_uniq(argv, "w"); + out = open_arg(argv, "w"); if (*argv && argv[1]) bb_show_usage(); - oldline = NULL; + line = skipped = NULL; +NOT_DUPLICATE: + oldline = line; + oldskipped = skipped; + dups = 0; + /* gnu uniq ignores newlines */ while ((line = bb_get_chomped_line_from_file(in)) != NULL) { skipped = line; @@ -70,27 +81,21 @@ int uniq_main(int argc, char **argv) } for (i = skip_chars ; *skipped && i ; i--) ++skipped; if (oldline) { - if (strcmp(oldskipped, skipped) == 0) { + if (!strcmp(oldskipped, skipped)) { ++dups; /* Note: Testing for overflow seems excessive. */ continue; } DO_LAST: - if ((dups && (uniq_flags & 2)) || (!dups && (uniq_flags & 4))) { - bb_fprintf(out, "\0%7d\t" + (uniq_flags & 1), dups + 1); + if (uniq_flags & (dups ? SHOW_DUPLICATE : SHOW_UNIQUE)) { + bb_fprintf(out, "\0%7d " + (uniq_flags & SHOW_COUNT), dups + 1); bb_fprintf(out, "%s\n", oldline); } free((void *)oldline); } - - oldline = line; - oldskipped = skipped; - dups = 0; + goto NOT_DUPLICATE; } - if (oldline) { - skipped = NULL; - goto DO_LAST; - } + if (oldline) goto DO_LAST; bb_xferror(in, input_filename); |