Changeset View
Changeset View
Standalone View
Standalone View
head/usr.bin/uniq/uniq.c
Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <termios.h> | #include <termios.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <wchar.h> | #include <wchar.h> | ||||
#include <wctype.h> | #include <wctype.h> | ||||
static int cflag, dflag, uflag, iflag; | static int Dflag, cflag, dflag, uflag, iflag; | ||||
static int numchars, numfields, repeats; | static int numchars, numfields, repeats; | ||||
/* Dflag values */ | |||||
#define DF_NONE 0 | |||||
#define DF_NOSEP 1 | |||||
#define DF_PRESEP 2 | |||||
#define DF_POSTSEP 3 | |||||
static const struct option long_opts[] = | static const struct option long_opts[] = | ||||
{ | { | ||||
{"all-repeated",optional_argument, NULL, 'D'}, | |||||
{"count", no_argument, NULL, 'c'}, | {"count", no_argument, NULL, 'c'}, | ||||
{"repeated", no_argument, NULL, 'd'}, | {"repeated", no_argument, NULL, 'd'}, | ||||
{"skip-fields", required_argument, NULL, 'f'}, | {"skip-fields", required_argument, NULL, 'f'}, | ||||
{"ignore-case", no_argument, NULL, 'i'}, | {"ignore-case", no_argument, NULL, 'i'}, | ||||
{"skip-chars", required_argument, NULL, 's'}, | {"skip-chars", required_argument, NULL, 's'}, | ||||
{"unique", no_argument, NULL, 'u'}, | {"unique", no_argument, NULL, 'u'}, | ||||
{NULL, no_argument, NULL, 0} | {NULL, no_argument, NULL, 0} | ||||
}; | }; | ||||
Show All 15 Lines | main (int argc, char *argv[]) | ||||
size_t prevbuflen, thisbuflen, b1; | size_t prevbuflen, thisbuflen, b1; | ||||
char *prevline, *thisline, *p; | char *prevline, *thisline, *p; | ||||
const char *ifn; | const char *ifn; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
(void) setlocale(LC_ALL, ""); | (void) setlocale(LC_ALL, ""); | ||||
obsolete(argv); | obsolete(argv); | ||||
while ((ch = getopt_long(argc, argv, "+cdif:s:u", long_opts, | while ((ch = getopt_long(argc, argv, "+D::cdif:s:u", long_opts, | ||||
NULL)) != -1) | NULL)) != -1) | ||||
switch (ch) { | switch (ch) { | ||||
case 'D': | |||||
if (optarg == NULL || strcasecmp(optarg, "none") == 0) | |||||
Dflag = DF_NOSEP; | |||||
else if (strcasecmp(optarg, "prepend") == 0) | |||||
Dflag = DF_PRESEP; | |||||
else if (strcasecmp(optarg, "separate") == 0) | |||||
Dflag = DF_POSTSEP; | |||||
else | |||||
usage(); | |||||
break; | |||||
case 'c': | case 'c': | ||||
cflag = 1; | cflag = 1; | ||||
break; | break; | ||||
case 'd': | case 'd': | ||||
dflag = 1; | dflag = 1; | ||||
break; | break; | ||||
case 'i': | case 'i': | ||||
iflag = 1; | iflag = 1; | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | if (tthis == NULL && tprev == NULL) | ||||
comp = inlcmp(thisline, prevline); | comp = inlcmp(thisline, prevline); | ||||
else if (tthis == NULL || tprev == NULL) | else if (tthis == NULL || tprev == NULL) | ||||
comp = 1; | comp = 1; | ||||
else | else | ||||
comp = wcscoll(tthis, tprev); | comp = wcscoll(tthis, tprev); | ||||
if (comp) { | if (comp) { | ||||
/* If different, print; set previous to new value. */ | /* If different, print; set previous to new value. */ | ||||
if (Dflag == DF_POSTSEP && repeats > 0) | |||||
fputc('\n', ofp); | |||||
if (!Dflag) | |||||
show(ofp, prevline); | show(ofp, prevline); | ||||
p = prevline; | p = prevline; | ||||
b1 = prevbuflen; | b1 = prevbuflen; | ||||
prevline = thisline; | prevline = thisline; | ||||
prevbuflen = thisbuflen; | prevbuflen = thisbuflen; | ||||
if (tprev != NULL) | if (tprev != NULL) | ||||
free(tprev); | free(tprev); | ||||
tprev = tthis; | tprev = tthis; | ||||
thisline = p; | thisline = p; | ||||
thisbuflen = b1; | thisbuflen = b1; | ||||
tthis = NULL; | tthis = NULL; | ||||
repeats = 0; | repeats = 0; | ||||
} else | } else { | ||||
if (Dflag) { | |||||
if (repeats == 0) { | |||||
if (Dflag == DF_PRESEP) | |||||
fputc('\n', ofp); | |||||
show(ofp, prevline); | |||||
} | |||||
show(ofp, thisline); | |||||
} | |||||
++repeats; | ++repeats; | ||||
} | } | ||||
} | |||||
if (ferror(ifp)) | if (ferror(ifp)) | ||||
err(1, "%s", ifn); | err(1, "%s", ifn); | ||||
if (!Dflag) | |||||
show(ofp, prevline); | show(ofp, prevline); | ||||
exit(0); | exit(0); | ||||
} | } | ||||
static wchar_t * | static wchar_t * | ||||
convert(const char *str) | convert(const char *str) | ||||
{ | { | ||||
size_t n; | size_t n; | ||||
wchar_t *buf, *ret, *p; | wchar_t *buf, *ret, *p; | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | |||||
* show -- | * show -- | ||||
* Output a line depending on the flags and number of repetitions | * Output a line depending on the flags and number of repetitions | ||||
* of the line. | * of the line. | ||||
*/ | */ | ||||
static void | static void | ||||
show(FILE *ofp, const char *str) | show(FILE *ofp, const char *str) | ||||
{ | { | ||||
if ((dflag && repeats == 0) || (uflag && repeats > 0)) | if ((!Dflag && dflag && repeats == 0) || (uflag && repeats > 0)) | ||||
return; | return; | ||||
if (cflag) | if (cflag) | ||||
(void)fprintf(ofp, "%4d %s", repeats + 1, str); | (void)fprintf(ofp, "%4d %s", repeats + 1, str); | ||||
else | else | ||||
(void)fprintf(ofp, "%s", str); | (void)fprintf(ofp, "%s", str); | ||||
} | } | ||||
static wchar_t * | static wchar_t * | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | while ((ap = *++argv)) { | ||||
*argv = start; | *argv = start; | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
usage(void) | usage(void) | ||||
{ | { | ||||
(void)fprintf(stderr, | (void)fprintf(stderr, | ||||
"usage: uniq [-c] [-d | -u] [-i] [-f fields] [-s chars] [input [output]]\n"); | "usage: uniq [-c | -d | -D | -u] [-i] [-f fields] [-s chars] [input [output]]\n"); | ||||
exit(1); | exit(1); | ||||
} | } |