diff options
| author | Jakob Kaivo <jkk@ung.org> | 2024-02-02 13:25:45 -0500 |
|---|---|---|
| committer | Jakob Kaivo <jkk@ung.org> | 2024-02-02 13:25:45 -0500 |
| commit | 24f39222098253da4ad1a9cd8ddef5b9b0152ba1 (patch) | |
| tree | 36eede312e7dcb4a9afe49342fba996ef273549d /src/stdio | |
| parent | 6aebe0dbfc24f0af73eb422b4748a9b35df5b435 (diff) | |
use UNDEFINED() instead of directly calling __undefined()
Diffstat (limited to 'src/stdio')
| -rw-r--r-- | src/stdio/__printf.c | 44 | ||||
| -rw-r--r-- | src/stdio/_stdio.h | 28 | ||||
| -rw-r--r-- | src/stdio/clearerr.c | 2 | ||||
| -rw-r--r-- | src/stdio/feof.c | 3 | ||||
| -rw-r--r-- | src/stdio/ferror.c | 2 | ||||
| -rw-r--r-- | src/stdio/fgetc.c | 3 | ||||
| -rw-r--r-- | src/stdio/freopen.c | 4 | ||||
| -rw-r--r-- | src/stdio/fseek.c | 11 |
8 files changed, 68 insertions, 29 deletions
diff --git a/src/stdio/__printf.c b/src/stdio/__printf.c index e86f91ee..7fa7a46b 100644 --- a/src/stdio/__printf.c +++ b/src/stdio/__printf.c @@ -169,15 +169,14 @@ int (__printf)(struct io_options *opt, const char * format, va_list arg) i++; if (format[i] == '*') { + /* TODO */ i++; } else if (isdigit(format[i])) { char *end; precision = (int)strtoumax(format + i, &end, 10); i = end - format; } else { - /* invalid precision */ - nout = -nout; - goto end; + precision = 0; } } @@ -216,25 +215,25 @@ int (__printf)(struct io_options *opt, const char * format, va_list arg) } if ((flags & ALT) && (!strchr("xXaAeEfFgG", format[i]))) { - __undefined("In call to %s(): The '#' flag is undefined for %%%c", opt->fnname, format[i]); + UNDEFINED("In call to %s(): The '#' flag is undefined for %%%c", opt->fnname, format[i]); } else if ((flags & ZERO) && (!strchr("diouxXaAeEfFgG", format[i]))) { - __undefined("In call to %s(): The '0' flag is undefined for %%%c", opt->fnname, format[i]); + UNDEFINED("In call to %s(): The '0' flag is undefined for %%%c", opt->fnname, format[i]); } else if ((length == hh) && (!strchr("diouxXn", format[i]))) { - __undefined("In call to %s(): The length 'hh' is undefined for %%%c", opt->fnname, format[i]); + UNDEFINED("In call to %s(): The length 'hh' is undefined for %%%c", opt->fnname, format[i]); } else if ((length == h) && (!strchr("diouxXn", format[i]))) { - __undefined("In call to %s(): The length 'h' is undefined for %%%c", opt->fnname, format[i]); + UNDEFINED("In call to %s(): The length 'h' is undefined for %%%c", opt->fnname, format[i]); } else if ((length == l) && (!strchr("diouxXncsaAeEfFgG", format[i]))) { - __undefined("In call to %s(): The length 'l' is undefined for %%%c", opt->fnname, format[i]); + UNDEFINED("In call to %s(): The length 'l' is undefined for %%%c", opt->fnname, format[i]); } else if ((length == ll) && (!strchr("diouxXn", format[i]))) { - __undefined("In call to %s(): The length 'll' is undefined for %%%c", opt->fnname, format[i]); + UNDEFINED("In call to %s(): The length 'll' is undefined for %%%c", opt->fnname, format[i]); } else if ((length == j) && (!strchr("diouxXn", format[i]))) { - __undefined("In call to %s(): The length 'j' is undefined for %%%c", opt->fnname, format[i]); + UNDEFINED("In call to %s(): The length 'j' is undefined for %%%c", opt->fnname, format[i]); } else if ((length == z) && (!strchr("diouxXn", format[i]))) { - __undefined("In call to %s(): The length 'z' is undefined for %%%c", opt->fnname, format[i]); + UNDEFINED("In call to %s(): The length 'z' is undefined for %%%c", opt->fnname, format[i]); } else if ((length == t) && (!strchr("diouxXn", format[i]))) { - __undefined("In call to %s(): The length 't' is undefined for %%%c", opt->fnname, format[i]); + UNDEFINED("In call to %s(): The length 't' is undefined for %%%c", opt->fnname, format[i]); } else if ((length == L) && (!strchr("aAeEfFgG", format[i]))) { - __undefined("In call to %s(): The length 'L' is undefined for %%%c", opt->fnname, format[i]); + UNDEFINED("In call to %s(): The length 'L' is undefined for %%%c", opt->fnname, format[i]); } switch (format[i]) { @@ -297,6 +296,10 @@ int (__printf)(struct io_options *opt, const char * format, va_list arg) break; case 'c': /* char */ + if (specified & PRECISION) { + UNDEFINED("In call to %s(): Precision with %%c conversions", opt->fnname); + } + if (length == def) { char c = va_arg(arg, int); if (nout < (int)n) { @@ -341,6 +344,9 @@ int (__printf)(struct io_options *opt, const char * format, va_list arg) break; case 'p': /* pointer */ + if (specified & PRECISION) { + UNDEFINED("In call to %s(): Precision with %%p conversion", opt->fnname); + } argptr = va_arg(arg, void *); nout = __append(s, "0x", nout, n); __itos(numbuf, (intptr_t)argptr, ZERO, sizeof(argptr) * 2, 16); @@ -349,13 +355,13 @@ int (__printf)(struct io_options *opt, const char * format, va_list arg) case 'n': /* write-back */ if (specified & FLAG) { - __undefined("In call to %s(): Flags with %%n conversion", opt->fnname); + UNDEFINED("In call to %s(): Flags with %%n conversion", opt->fnname); } else if (specified & 0) { /* TODO: output suppression (might only be for input) */ } else if (specified & WIDTH) { - __undefined("In call to %s(): Width with %%n conversion", opt->fnname); + UNDEFINED("In call to %s(): Width with %%n conversion", opt->fnname); } else if (specified & PRECISION) { - __undefined("In call to %s(): Precision with %%n conversion", opt->fnname); + UNDEFINED("In call to %s(): Precision with %%n conversion", opt->fnname); } switch (length) { @@ -392,13 +398,13 @@ int (__printf)(struct io_options *opt, const char * format, va_list arg) *pd = nout; break; case L: - __undefined("In call to %s(): Invalid length 'L' for %%n conversion", opt->fnname); + UNDEFINED("In call to %s(): Invalid length 'L' for %%n conversion", opt->fnname); } break; case '%': /* literal '%' */ if (specified != 0) { - __undefined("In call to %s(): \"%%%%\" conversion is not literally \"%%%%\"", opt->fnname); + UNDEFINED("In call to %s(): \"%%%%\" conversion is not literally \"%%%%\"", opt->fnname); } if (nout < (int)n) { s[nout] = '%'; @@ -407,7 +413,7 @@ int (__printf)(struct io_options *opt, const char * format, va_list arg) break; default: /* undefined */ - __undefined("In call to %s(): Unknown conversion specifier %%%c", opt->fnname, format[i]); + UNDEFINED("In call to %s(): Unknown conversion specifier %%%c", opt->fnname, format[i]); } } diff --git a/src/stdio/_stdio.h b/src/stdio/_stdio.h index 516ce659..d47ac5dd 100644 --- a/src/stdio/_stdio.h +++ b/src/stdio/_stdio.h @@ -22,6 +22,23 @@ #define GCC_SSE_HACK __attribute__((noinline, target("no-sse"))) +#define ORIENT_WIDE (1) +#define ORIENT_BYTE (-1) + +#define OP_INPUT (1) +#define OP_OUTPUT (2) + +#ifdef NDEBUG +#define ASSERT_STREAM(__stream, __orientation, __operation) +#else +#define ASSERT_STREAM(__stream, __orientation, __operation) do { \ + ASSERT_NONNULL(__stream); \ + if (((__orientation) && stream->orientation) && ((__orientation) != stream->orientation)) { \ + UNDEFINED("In call to %s(): Requested %s operation on %s oriented stream", __func__, (__orientation) > 0 ? "wide" : "byte", (stream->orientation) > 0 ? "wide" : "byte"); \ + } \ + } while (0) +#endif + struct __FILE { fpos_t pos; @@ -38,14 +55,15 @@ struct __FILE { int fd; /* the backing file descriptor */ - int orientation; /* 0 = undetermind, < 0 = byte, > 0 = wide */ - - int eof; /* eof indicator */ - int err; /* error indicator */ - int nlocks; /* in multithreaded, used by flockfile() */ int thread; /* the owning thread if locked */ + int orientation:2; /* 0 = undetermind, < 0 = byte, > 0 = wide */ + int operation; /* TODO: previous operation, NONE, INPUT, OUTPUT (are there others?) */ + int eof:1; /* eof indicator */ + int err:1; /* error indicator */ + int text:1; /* is this a text file? */ + #ifdef _POSIX_C_SOURCE pid_t pipe_pid; /* if stream is a pipe, the child pid */ #endif diff --git a/src/stdio/clearerr.c b/src/stdio/clearerr.c index f7d2aac1..9f13851e 100644 --- a/src/stdio/clearerr.c +++ b/src/stdio/clearerr.c @@ -7,6 +7,8 @@ void clearerr(FILE * stream) { SIGNAL_SAFE(0); + ASSERT_STREAM(stream, 0, 0); + flockfile(stream); if (stream != NULL) { stream->eof = 0; diff --git a/src/stdio/feof.c b/src/stdio/feof.c index 39d9b645..fdcb9ea9 100644 --- a/src/stdio/feof.c +++ b/src/stdio/feof.c @@ -6,7 +6,8 @@ int feof(FILE *stream) { SIGNAL_SAFE(0); - ASSERT_NONNULL(stream); + ASSERT_STREAM(stream, 0, 0); + flockfile(stream); if (stream->eof) { diff --git a/src/stdio/ferror.c b/src/stdio/ferror.c index 66299ab9..1d2fcc8d 100644 --- a/src/stdio/ferror.c +++ b/src/stdio/ferror.c @@ -6,7 +6,7 @@ int ferror(FILE *stream) { SIGNAL_SAFE(0); - ASSERT_NONNULL(stream); + ASSERT_STREAM(stream, 0, 0); /* RETURN(0, the error indicator is not set); RETURN(NONZERO, the error indicator is set); diff --git a/src/stdio/fgetc.c b/src/stdio/fgetc.c index 06e4c064..2bae1eb7 100644 --- a/src/stdio/fgetc.c +++ b/src/stdio/fgetc.c @@ -12,9 +12,12 @@ int fgetc(FILE *stream) { SIGNAL_SAFE(0); + ASSERT_STREAM(stream, ORIENT_BYTE, OP_INPUT); + flockfile(stream); char c = getc_unlocked(stream); funlockfile(stream); + /* RETURN_SUCCESS(the next character); RETURN_FAILURE(CONSTANT(EOF)); diff --git a/src/stdio/freopen.c b/src/stdio/freopen.c index 0fd0a2f8..3a1ef656 100644 --- a/src/stdio/freopen.c +++ b/src/stdio/freopen.c @@ -70,7 +70,7 @@ FILE * freopen(const char * restrict filename, const char * restrict mode, FILE } if (openmode == -1) { - __undefined("\"%s\" is not a valid mode for fopen() or freopen()", mode); + UNDEFINED("\"%s\" is not a valid mode for fopen() or freopen()", mode); #ifdef EINVAL errno = EINVAL; #endif @@ -96,6 +96,8 @@ FILE * freopen(const char * restrict filename, const char * restrict mode, FILE stream->buf = stream->ibuf; } + stream->text = !(strchr(mode, 'b')); + /* RETURN_SUCCESS(ARGUMENT(stream)); RETURN_FAILURE(CONSTANT(NULL)); diff --git a/src/stdio/fseek.c b/src/stdio/fseek.c index e1c6db57..47388c9a 100644 --- a/src/stdio/fseek.c +++ b/src/stdio/fseek.c @@ -6,8 +6,15 @@ int fseek(FILE *stream, long int offset, int whence) { SIGNAL_SAFE(0); - - (void)stream; (void)offset; + ASSERT_STREAM(stream, 0, 0); + + if (stream->text && offset != 0) { + if (whence != SEEK_SET) { + UNDEFINED("In call to fseek(): Only SEEK_SET is supported for text files"); + } + /* if offset is not previous */ + /* UNDEFINED("fseek() on text files requires an offset previously returned by ftell()"); */ + } if (whence == SEEK_CUR) { } else if (whence == SEEK_END) { |
