sbase

suckless unix tools
git clone git://git.2f30.org/sbase
Log | Files | Refs | README | LICENSE

commit 85efaad43b62f999713589c64134dd2d2aff32a5
parent 85b84675f1c519837e82925fcc3654d05a6f10cd
Author: Robert Ransom <rransom.8774@gmail.com>
Date:   Mon, 21 May 2012 23:24:28 +0000

uniq: Initial commit
Diffstat:
MMakefile | 3++-
Auniq.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile @@ -54,6 +54,7 @@ SRC = \ true.c \ tty.c \ uname.c \ + uniq.c \ seq.c \ wc.c \ yes.c @@ -66,7 +67,7 @@ all: $(BIN) $(OBJ): util.h config.mk $(BIN): util.a -cat.o fold.o grep.o nl.o sort.o tail.o: text.h +cat.o fold.o grep.o nl.o sort.o tail.o uniq.o: text.h cp.o mv.o rm.o: fs.h .o: diff --git a/uniq.c b/uniq.c @@ -0,0 +1,96 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "text.h" +#include "util.h" + +static void uniq_line(char *); +static void uniq(FILE *, const char *); +static void uniq_finish(void); + +static const char *countfmt = ""; +static bool dflag = false; +static bool uflag = false; + +static char *prev_line = NULL; +static long prev_line_count = 0; + +int +main(int argc, char *argv[]) +{ + int c; + FILE *fp; + + while((c = getopt(argc, argv, "cdu")) != -1) + switch(c) { + case 'c': + countfmt = "%7ld "; + break; + case 'd': + dflag = true; + break; + case 'u': + uflag = true; + break; + default: + exit(2); + } + + if(optind == argc) + uniq(stdin, "<stdin>"); + else for(; optind < argc; optind++) { + if(!(fp = fopen(argv[optind], "r"))) + eprintf("fopen %s:", argv[optind]); + uniq(fp, argv[optind]); + fclose(fp); + } + uniq_finish(); + + return EXIT_SUCCESS; +} + +void +uniq_line(char *l) +{ + bool lines_equal = ((l == NULL) || (prev_line == NULL)) + ? l == prev_line + : !strcmp(l, prev_line); + + if(lines_equal) { + ++prev_line_count; + return; + } + + if(prev_line != NULL) { + if((prev_line_count == 1 && !dflag) || + (prev_line_count != 1 && !uflag)) { + printf(countfmt, prev_line_count); + fputs(prev_line, stdout); + } + free(prev_line); + prev_line = NULL; + } + + if(l && !(prev_line = strdup(l))) + eprintf("strdup:"); + prev_line_count = 1; +} + +void +uniq(FILE *fp, const char *str) +{ + char *buf = NULL; + size_t size = 0; + + while(afgets(&buf, &size, fp)) + uniq_line(buf); +} + +void +uniq_finish() +{ + uniq_line(NULL); +}