aboutsummaryrefslogtreecommitdiff
path: root/usr.bin/tr/tr.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/tr/tr.c')
-rw-r--r--usr.bin/tr/tr.c45
1 files changed, 40 insertions, 5 deletions
diff --git a/usr.bin/tr/tr.c b/usr.bin/tr/tr.c
index 033b75cb5300..6eea2cb60409 100644
--- a/usr.bin/tr/tr.c
+++ b/usr.bin/tr/tr.c
@@ -68,8 +68,10 @@ static void usage(void);
int
main(int argc, char **argv)
{
+ static int carray[NCHARS_SB];
struct cmap *map;
struct cset *delete, *squeeze;
+ int n, *p;
int Cflag, cflag, dflag, sflag, isstring2;
wint_t ch, cnt, lastch;
@@ -252,7 +254,7 @@ main(int argc, char **argv)
(void)next(&s2);
}
endloop:
- if (cflag || Cflag) {
+ if (cflag || (Cflag && MB_CUR_MAX > 1)) {
/*
* This is somewhat tricky: since the character set is
* potentially huge, we need to avoid allocating a map
@@ -270,11 +272,10 @@ endloop:
if (Cflag && !iswrune(cnt))
continue;
if (cmap_lookup(map, cnt) == OOBCH) {
- if (next(&s2)) {
+ if (next(&s2))
cmap_add(map, cnt, s2.lastch);
- if (sflag)
- cset_add(squeeze, s2.lastch);
- }
+ if (sflag)
+ cset_add(squeeze, s2.lastch);
} else
cmap_add(map, cnt, cnt);
if ((s2.state == EOS || s2.state == INFINITE) &&
@@ -282,6 +283,30 @@ endloop:
break;
}
cmap_default(map, s2.lastch);
+ } else if (Cflag) {
+ for (p = carray, cnt = 0; cnt < NCHARS_SB; cnt++) {
+ if (cmap_lookup(map, cnt) == OOBCH && iswrune(cnt))
+ *p++ = cnt;
+ else
+ cmap_add(map, cnt, cnt);
+ }
+ n = p - carray;
+ if (Cflag && n > 1)
+ (void)mergesort(carray, n, sizeof(*carray), charcoll);
+
+ s2.str = argv[1];
+ s2.state = NORMAL;
+ for (cnt = 0; cnt < n; cnt++) {
+ (void)next(&s2);
+ cmap_add(map, carray[cnt], s2.lastch);
+ /*
+ * Chars taken from s2 can be different this time
+ * due to lack of complex upper/lower processing,
+ * so fill string2 again to not miss some.
+ */
+ if (sflag)
+ cset_add(squeeze, s2.lastch);
+ }
}
cset_cache(squeeze);
@@ -326,6 +351,16 @@ setup(char *arg, STR *str, int cflag, int Cflag)
return (cs);
}
+int
+charcoll(const void *a, const void *b)
+{
+ static char sa[2], sb[2];
+
+ sa[0] = *(const int *)a;
+ sb[0] = *(const int *)b;
+ return (strcoll(sa, sb));
+}
+
static void
usage(void)
{