2012-05-21 19:24:28 -04:00
|
|
|
/* See LICENSE file for copyright and license details. */
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2013-03-05 15:35:55 -05:00
|
|
|
|
2012-05-21 19:24:28 -04:00
|
|
|
#include "text.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
2014-01-20 05:47:46 -05:00
|
|
|
static void uniqline(char *);
|
2012-05-21 19:24:28 -04:00
|
|
|
static void uniq(FILE *, const char *);
|
2014-01-20 05:47:46 -05:00
|
|
|
static void uniqfinish(void);
|
2012-05-21 19:24:28 -04:00
|
|
|
|
|
|
|
static const char *countfmt = "";
|
|
|
|
static bool dflag = false;
|
|
|
|
static bool uflag = false;
|
|
|
|
|
2014-01-20 05:47:46 -05:00
|
|
|
static char *prevline = NULL;
|
|
|
|
static long prevlinecount = 0;
|
2012-05-21 19:24:28 -04:00
|
|
|
|
2013-06-14 14:20:47 -04:00
|
|
|
static void
|
|
|
|
usage(void)
|
|
|
|
{
|
2013-08-15 05:55:21 -04:00
|
|
|
eprintf("usage: %s [-cdiu] [input]]\n", argv0);
|
2013-06-14 14:20:47 -04:00
|
|
|
}
|
|
|
|
|
2012-05-21 19:24:28 -04:00
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
|
2013-06-14 14:20:47 -04:00
|
|
|
ARGBEGIN {
|
2013-08-15 05:55:21 -04:00
|
|
|
case 'i':
|
|
|
|
eprintf("not implemented\n");
|
2013-06-14 14:20:47 -04:00
|
|
|
case 'c':
|
|
|
|
countfmt = "%7ld ";
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
dflag = true;
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
uflag = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage();
|
|
|
|
} ARGEND;
|
2012-05-21 19:24:28 -04:00
|
|
|
|
2013-06-14 14:20:47 -04:00
|
|
|
if(argc == 0) {
|
2012-05-21 19:24:28 -04:00
|
|
|
uniq(stdin, "<stdin>");
|
2013-06-14 14:20:47 -04:00
|
|
|
} else if(argc == 1) {
|
|
|
|
if(!(fp = fopen(argv[0], "r")))
|
|
|
|
eprintf("fopen %s:", argv[0]);
|
|
|
|
uniq(fp, argv[0]);
|
2012-05-21 19:24:28 -04:00
|
|
|
fclose(fp);
|
2012-05-21 19:33:36 -04:00
|
|
|
} else
|
2013-06-14 14:20:47 -04:00
|
|
|
usage();
|
2014-01-20 05:47:46 -05:00
|
|
|
uniqfinish();
|
2012-05-21 19:24:28 -04:00
|
|
|
|
2013-10-07 11:41:55 -04:00
|
|
|
return EXIT_SUCCESS;
|
2012-05-21 19:24:28 -04:00
|
|
|
}
|
|
|
|
|
2014-06-01 08:59:47 -04:00
|
|
|
static void
|
2014-01-20 05:47:46 -05:00
|
|
|
uniqline(char *l)
|
2012-05-21 19:24:28 -04:00
|
|
|
{
|
2014-06-01 08:59:47 -04:00
|
|
|
bool linesequel = ((l == NULL) || (prevline == NULL))
|
2014-01-20 05:47:46 -05:00
|
|
|
? l == prevline
|
|
|
|
: !strcmp(l, prevline);
|
2012-05-21 19:24:28 -04:00
|
|
|
|
2014-06-01 08:59:47 -04:00
|
|
|
if(linesequel) {
|
2014-01-20 05:47:46 -05:00
|
|
|
++prevlinecount;
|
2012-05-21 19:24:28 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-20 05:47:46 -05:00
|
|
|
if(prevline != NULL) {
|
|
|
|
if((prevlinecount == 1 && !dflag) ||
|
|
|
|
(prevlinecount != 1 && !uflag)) {
|
|
|
|
printf(countfmt, prevlinecount);
|
|
|
|
fputs(prevline, stdout);
|
2012-05-21 19:24:28 -04:00
|
|
|
}
|
2014-01-20 05:47:46 -05:00
|
|
|
free(prevline);
|
|
|
|
prevline = NULL;
|
2012-05-21 19:24:28 -04:00
|
|
|
}
|
|
|
|
|
2014-01-20 05:47:46 -05:00
|
|
|
if(l && !(prevline = strdup(l)))
|
2012-05-21 19:24:28 -04:00
|
|
|
eprintf("strdup:");
|
2014-01-20 05:47:46 -05:00
|
|
|
prevlinecount = 1;
|
2012-05-21 19:24:28 -04:00
|
|
|
}
|
|
|
|
|
2014-06-01 08:59:47 -04:00
|
|
|
static void
|
2012-05-21 19:24:28 -04:00
|
|
|
uniq(FILE *fp, const char *str)
|
|
|
|
{
|
|
|
|
char *buf = NULL;
|
|
|
|
size_t size = 0;
|
|
|
|
|
|
|
|
while(afgets(&buf, &size, fp))
|
2014-01-20 05:47:46 -05:00
|
|
|
uniqline(buf);
|
2012-05-21 19:24:28 -04:00
|
|
|
}
|
|
|
|
|
2014-06-01 08:59:47 -04:00
|
|
|
static void
|
|
|
|
uniqfinish(void)
|
2012-05-21 19:24:28 -04:00
|
|
|
{
|
2014-01-20 05:47:46 -05:00
|
|
|
uniqline(NULL);
|
2012-05-21 19:24:28 -04:00
|
|
|
}
|