/* Author: Ruud Harmsen, September 2021. Explanation: https://rudhar.com/sfreview/siworin/siworin17.htm Further illustration of this bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28258 */ #include #include #include #include #include #include #include #define REPERR(LINE, ERRNO) { \ fprintf(stderr, "Line %3d, error %d ", (LINE), (ERRNO)); \ perror(NULL);} int main (int argc, char **argv) { static char bytes1[] = u8"Bênção\n"; static char bytes2[] = "B\352n\347\343o\n"; FILE *fp; wint_t wc; int c; long pos; long beforeread = 0; if (!setlocale(LC_ALL, "en_US.UTF-8")) REPERR(__LINE__, errno); /* Write the test string to disk. */ fp = fopen("in", "w"); fwrite(bytes1, 1, sizeof bytes1 - 1, fp); fwrite(bytes2, 1, sizeof bytes2 - 1, fp); fwrite(bytes1, 1, sizeof bytes1 - 1, fp); fclose(fp); /* Reopen for reading. */ fp = fopen("in", "r"); while (pos = ftell(fp), wc = fgetwc(fp), !feof(fp)) { printf("Line %3d, ftell %3ld>%3ld. ", __LINE__, pos, ftell(fp)); if (ferror(fp) && errno == EILSEQ) { clearerr(fp); /* Skip one byte and continue */ if (argc > 1) { printf("...fseek"); fflush(stdout); if (fseek(fp, beforeread + 1, SEEK_SET)) REPERR(__LINE__, errno); printf("... "); fflush(stdout); } else { c = fgetc(fp); printf("Line %3d, byte c %c %02x. ", __LINE__, isprint(c) ? c : '=', (int)c); } } printf("Line %3d, wide character %lc %04x\n", __LINE__, iswprint(wc) ? wc : '=', (int)wc); if (wc == WEOF) wc = '-'; { char s[MB_CUR_MAX]; beforeread += wctomb(s, wc); } } fclose(fp); return 0; }