diff options
Diffstat (limited to 'usr.bin/tr/tr.c')
-rw-r--r-- | usr.bin/tr/tr.c | 45 |
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) { |