#include <sys/types.h>
#include <err.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wchar.h>
char filename[] = "/tmp/fwide.XXXXXXXXXX";
FILE *dup_stdout = NULL;
int failures = 0;
void
fail(int line, int r, char const *expect, char const *test)
{
failures++;
fprintf(dup_stdout,
"FAIL: %d: fwide returned %d, expected %s 0 after %s\n",
line, r, expect, test);
}
FILE *
setup(int line)
{
FILE *f;
int r;
if ((f = fopen(filename, "r+")) == NULL)
err(2, "fopen");
if ((r = fwide(f, 0)) != 0)
fail(line, r, "==", "fopen");
return (f);
}
FILE *
setup_std(FILE *std, int line)
{
int r;
if (freopen(filename, "r+", std) == NULL)
err(2, "freopen");
if ((r = fwide(std, 0)) != 0)
fail(line, r, "==", "freopen");
return (std);
}
#define TEST_(x, op) \
do { \
f = setup(__LINE__); \
x; \
if (!((r = fwide(f, 0)) op 0)) \
fail(__LINE__, r, #op, #x); \
fclose(f); \
} while (0)
#define TEST_STD_(std, x, op) \
do { \
f = setup_std(std, __LINE__); \
x; \
if (!((r = fwide(f, 0)) op 0)) \
fail(__LINE__, r, #op, #x); \
} while (0)
#define TEST_UNCHANGED(x) TEST_(x, ==)
#define TEST_NARROW(x) TEST_(x, <)
#define TEST_WIDE(x) TEST_(x, >)
#define TEST_UNCHANGED_STD(std, x) TEST_STD_(std, x, ==)
#define TEST_NARROW_STD(std, x) TEST_STD_(std, x, <)
#define TEST_WIDE_STD(std, x) TEST_STD_(std, x, >)
int
main(int argc, char *argv[])
{
char buffer[BUFSIZ];
wchar_t wbuffer[BUFSIZ];
char *buf;
wchar_t *wbuf;
FILE *f;
off_t off;
fpos_t pos;
size_t size;
int fd, r;
char c;
wchar_t wc;
if ((fd = dup(1)) == -1)
err(2, "dup");
if ((dup_stdout = fdopen(fd, "w")) == NULL)
err(2, "fdopen");
if ((fd = mkstemp(filename)) == -1)
err(2, "mkstemp");
if (write(fd, "0123456789\n\n", 12) != 12 || close(fd))
err(2, "write + close");
TEST_UNCHANGED(fwide(f, 0));
TEST_NARROW(fwide(f, -1));
TEST_WIDE(fwide(f, 1));
TEST_UNCHANGED(feof(f));
TEST_UNCHANGED(ferror(f));
TEST_UNCHANGED(fileno(f));
TEST_UNCHANGED(clearerr(f));
TEST_UNCHANGED(fflush(f));
TEST_UNCHANGED(fpurge(f));
TEST_UNCHANGED(fgetpos(f, &pos));
TEST_UNCHANGED(fgetpos(f, &pos); fsetpos(f, &pos));
TEST_UNCHANGED(ftell(f));
TEST_UNCHANGED(ftello(f));
TEST_UNCHANGED(fseek(f, 1, SEEK_CUR));
TEST_UNCHANGED(fseek(f, 1, SEEK_SET));
TEST_UNCHANGED(fseek(f, 1, SEEK_END));
TEST_UNCHANGED(fseeko(f, 1, SEEK_CUR));
TEST_UNCHANGED(fseeko(f, 1, SEEK_SET));
TEST_UNCHANGED(fseeko(f, 1, SEEK_END));
TEST_UNCHANGED(rewind(f));
TEST_UNCHANGED(setbuf(f, NULL));
TEST_UNCHANGED(setbuf(f, buffer));
TEST_UNCHANGED(setvbuf(f, buffer, _IONBF, BUFSIZ));
TEST_UNCHANGED(setvbuf(f, buffer, _IOLBF, BUFSIZ));
TEST_UNCHANGED(setvbuf(f, buffer, _IOFBF, BUFSIZ));
TEST_UNCHANGED(setvbuf(f, NULL, _IONBF, 0));
TEST_UNCHANGED(setvbuf(f, NULL, _IOLBF, 0));
TEST_UNCHANGED(setvbuf(f, NULL, _IOFBF, 0));
TEST_UNCHANGED(setbuffer(f, NULL, 0));
TEST_UNCHANGED(setbuffer(f, buffer, BUFSIZ));
TEST_UNCHANGED(setlinebuf(f));
TEST_UNCHANGED(flockfile(f);funlockfile(f));
TEST_UNCHANGED(ftrylockfile(f);funlockfile(f));
TEST_NARROW(getc(f));
TEST_NARROW(getc_unlocked(f));
TEST_NARROW(fgetc(f));
TEST_NARROW(c = fgetc(f); ungetc(c, f));
TEST_NARROW(fgets(buffer, BUFSIZ, f));
TEST_NARROW(fscanf(f, "%s\n", buffer));
TEST_NARROW(fgetln(f, &size));
TEST_NARROW(putc('c', f));
TEST_NARROW(putc_unlocked('c', f));
TEST_NARROW(fputc('c', f));
TEST_NARROW(fputs("foo", f));
TEST_NARROW(fprintf(f, "%s\n", "foo"));
TEST_NARROW_STD(stdin, getchar());
TEST_NARROW_STD(stdin, getchar_unlocked());
TEST_NARROW_STD(stdin, scanf("%s\n", buffer));
TEST_NARROW_STD(stdout, putchar('c'));
TEST_NARROW_STD(stdout, putchar_unlocked('c'));
TEST_NARROW_STD(stdout, puts("foo"));
TEST_NARROW_STD(stdout, printf("foo"));
TEST_NARROW(fread(buffer, 4, BUFSIZ / 4, f));
TEST_NARROW(fwrite(buffer, 4, BUFSIZ / 4, f));
TEST_NARROW(getw(f));
TEST_NARROW(putw(1234, f));
TEST_WIDE(getwc(f));
TEST_WIDE(fgetwc(f));
TEST_WIDE(wc = fgetwc(f); ungetwc(wc, f));
TEST_WIDE(fgetws(wbuffer, BUFSIZ, f));
TEST_WIDE(fwscanf(f, L"%s\n", wbuffer));
TEST_WIDE(putwc(L'c', f));
TEST_WIDE(fputwc(L'c', f));
TEST_WIDE(fputws(L"foo", f));
TEST_WIDE(fwprintf(f, L"%s\n", L"foo"));
TEST_WIDE_STD(stdin, getwchar());
TEST_WIDE_STD(stdin, wscanf(L"%s\n", wbuffer));
TEST_WIDE_STD(stdout, putwchar(L'c'));
TEST_WIDE_STD(stdout, wprintf(L"foo"));
f = open_memstream(&buf, &size);
if (!((r = fwide(f, 0)) < 0))
fail(__LINE__, r, "<", "open_memstream()");
fclose(f);
f = open_wmemstream(&wbuf, &size);
if (!((r = fwide(f, 0)) > 0))
fail(__LINE__, r, ">", "open_wmemstream()");
fclose(f);
TEST_UNCHANGED_STD(stderr, perror("foo"));
remove(filename);
if (failures)
exit(1);
exit(0);
}