--- /usr/src/bin/cat/cat.c 2016-07-22 16:42:11.671288000 +0300 +++ cat.c 2016-08-05 17:34:58.835826000 +0300 @@ -51,11 +51,11 @@ #ifndef NO_UDOM_SUPPORT #include #include -#include #endif #include #include +#include #include #include #include @@ -63,6 +63,8 @@ #include #include #include +#include +#include static int bflag, eflag, lflag, nflag, sflag, tflag, vflag; static int rval; @@ -204,60 +206,119 @@ static void cook_cat(FILE *fp) { - int ch, gobble, line, prev; + int c, oc, gobble, line, saverrno; + wint_t ch, och, prev; /* Reset EOF condition on stdin. */ if (fp == stdin && feof(stdin)) clearerr(stdin); + saverrno = errno; line = gobble = 0; - for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { - if (prev == '\n') { + prev = L'\n'; +again: + errno = 0; + for (; (ch = getwc(fp)) != WEOF; prev = ch) { + if (prev == L'\n') { if (sflag) { - if (ch == '\n') { + if (ch == L'\n') { if (gobble) continue; gobble = 1; } else gobble = 0; } - if (nflag && (!bflag || ch != '\n')) { + if (nflag && (!bflag || ch != L'\n')) { (void)fprintf(stdout, "%6d\t", ++line); if (ferror(stdout)) break; } } - if (ch == '\n') { + och = WEOF; + if (ch == L'\n') { if (eflag && putchar('$') == EOF) break; - } else if (ch == '\t') { + } else if (ch == L'\t') { if (tflag) { if (putchar('^') == EOF || putchar('I') == EOF) break; continue; } } else if (vflag) { - if (!isascii(ch) && !isprint(ch)) { + if (!iswprint(ch)) { if (putchar('M') == EOF || putchar('-') == EOF) break; + och = ch; ch = toascii(ch); } - if (iscntrl(ch)) { + if (iswcntrl(ch)) { + if (och != WEOF) { + och = ch; + ch = toascii(ch); + } if (putchar('^') == EOF || - putchar(ch == '\177' ? '?' : - ch | 0100) == EOF) + putwchar(ch == L'\177' ? L'?' : + ch | 0100) == WEOF) break; + ch = och; continue; } } - if (putchar(ch) == EOF) + if (putwchar(ch) == WEOF) break; + if (och != WEOF) + ch = och; } + if (!ferror(stdout) && !feof(fp) && ferror(fp) && errno == EILSEQ) { + if ((c = getc(fp)) != EOF) { + if (prev == L'\n') { + if (sflag) + gobble = 0; + if (nflag) { + (void)fprintf(stdout, "%6d\t", ++line); + if (ferror(stdout)) + goto err; + } + } + oc = EOF; + if (vflag) { + if (c >= ' ' && c != '\177') { + if (putchar('M') == EOF || putchar('-') == EOF) + goto err; + oc = c; + c = toascii(c); + } + if (c < ' ' || c == '\177') { + if (putchar('^') == EOF || + putchar(c == '\177' ? '?' : + c | 0100) == EOF) + goto err; + if (oc != EOF) + c = oc; + prev = c; + clearerr(fp); + goto again; + } + } + if (putchar(c) == EOF) + goto err; + if (oc != EOF) + c = oc; + prev = c; + clearerr(fp); + goto again; + } + } +err: if (ferror(fp)) { - warn("%s", filename); - rval = 1; + if (errno != EILSEQ) { + warn("%s", filename); + rval = 1; + } clearerr(fp); } + if (errno == 0) + errno = saverrno; if (ferror(stdout)) err(1, "stdout"); }