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 | |
parent | 6aebe0dbfc24f0af73eb422b4748a9b35df5b435 (diff) |
use UNDEFINED() instead of directly calling __undefined()
-rw-r--r-- | src/_safety.h | 6 | ||||
-rw-r--r-- | src/assert/assert.c | 2 | ||||
-rw-r--r-- | src/ctype/_ctype.h | 2 | ||||
-rw-r--r-- | src/fenv/_fenv.h | 2 | ||||
-rw-r--r-- | src/signal/__signal_handler.c | 4 | ||||
-rw-r--r-- | src/signal/raise.c | 2 | ||||
-rw-r--r-- | src/stdarg/va_arg.c | 2 | ||||
-rw-r--r-- | src/stdarg/va_copy.c | 2 | ||||
-rw-r--r-- | src/stdarg/va_end.c | 2 | ||||
-rw-r--r-- | src/stdarg/va_start.c | 2 | ||||
-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 | ||||
-rw-r--r-- | src/stdlib/_stdlib.h | 2 | ||||
-rw-r--r-- | src/stdlib/bsearch.c | 2 | ||||
-rw-r--r-- | src/time/asctime.c | 2 |
21 files changed, 84 insertions, 45 deletions
diff --git a/src/_safety.h b/src/_safety.h index 15076cc8..37b66915 100644 --- a/src/_safety.h +++ b/src/_safety.h @@ -30,7 +30,7 @@ extern struct __checked_call { #define ASSERT_NONNULL(__ptr) do { \ if (!__ptr) { \ - __undefined("In call to %s(), parameter %s cannot be NULL", __func__, #__ptr); \ + UNDEFINED("In call to %s(), parameter %s cannot be NULL", __func__, #__ptr); \ } \ } while (0) @@ -38,14 +38,14 @@ extern struct __checked_call { char *__s1 = (char*)(__p1); \ char *__s2 = (char*)(__p2); \ if (((__s1 < __s2) && ((__s1 + (__l1)) >= __s2)) || ((__s1 > __s2) && ((__s2 + (__l2)) >= __s1))) { \ - __undefined("In call to %s(), parameters %s and %s overlap", __func__, #__p1, #__p2); \ + UNDEFINED("In call to %s(), parameters %s and %s overlap", __func__, #__p1, #__p2); \ } \ } while (0) #define SIGNAL_SAFE(__n) do { \ if (__n == 0 && ___signal.current != 0) { \ int _sig = ___signal.current; \ - __undefined("Function %s() is not safe to call from a signal handler (signal %d)", __func__, _sig); \ + UNDEFINED("Function %s() is not safe to call from a signal handler (signal %d)", __func__, _sig); \ } \ } while (0) diff --git a/src/assert/assert.c b/src/assert/assert.c index 8fbc5daf..e25f3d1b 100644 --- a/src/assert/assert.c +++ b/src/assert/assert.c @@ -2,7 +2,7 @@ void assert() { - __undefined("The assert() macro has been suppressed to access an actual function"); + UNDEFINED("The assert() macro has been suppressed to access an actual function"); } /* diff --git a/src/ctype/_ctype.h b/src/ctype/_ctype.h index dbb13ab1..d167ef8b 100644 --- a/src/ctype/_ctype.h +++ b/src/ctype/_ctype.h @@ -12,7 +12,7 @@ #else #define ASSERT_REPRESENTABLE(_n, _min, _max, _type, _sentinel) do { \ if (!(((_n) == (_sentinel)) || (((_min) <= (_n)) && ((_n) <= (_max))))) { \ - __undefined("In call to %s(), parameter %s (value 0x%ju) is not representable as a %s (range [%s, %s]) or exactly %s", __func__, #_n, (uintmax_t)(_n), #_type, #_min, #_max, #_sentinel); \ + UNDEFINED("In call to %s(), parameter %s (value 0x%ju) is not representable as a %s (range [%s, %s]) or exactly %s", __func__, #_n, (uintmax_t)(_n), #_type, #_min, #_max, #_sentinel); \ } \ } while (0) #endif diff --git a/src/fenv/_fenv.h b/src/fenv/_fenv.h index 718bd136..eaaa7d0c 100644 --- a/src/fenv/_fenv.h +++ b/src/fenv/_fenv.h @@ -8,7 +8,7 @@ #else #define ASSERT_VALID_EXCEPTION_MASK(_n) do { \ if (((_n) & ~(FE_ALL_EXCEPT)) != 0) { \ - __undefined("In call to %s(), exception mask 0x(%jx) is not valid", __func__, (uintmax_t)(_n)); \ + UNDEFINED("In call to %s(), exception mask 0x(%jx) is not valid", __func__, (uintmax_t)(_n)); \ } \ } while (0) diff --git a/src/signal/__signal_handler.c b/src/signal/__signal_handler.c index 0c0fd719..c7a4675c 100644 --- a/src/signal/__signal_handler.c +++ b/src/signal/__signal_handler.c @@ -6,7 +6,7 @@ void __signal_handler(int sig) { if (__stdlib.exit_called == QUICK) { - __undefined("signal %d occured during quick_exit", sig); + UNDEFINED("signal %d occured during quick_exit", sig); } ___signal.current = sig; @@ -17,7 +17,7 @@ void __signal_handler(int sig) /* TODO: signal number to name */ if (sig == SIGFPE || sig == SIGILL || sig == SIGSEGV) { ___signal.current = 0; - __undefined("Signal handler for signal %d returned", sig); + UNDEFINED("Signal handler for signal %d returned", sig); } ___signal.current = 0; diff --git a/src/signal/raise.c b/src/signal/raise.c index 44bf1b58..7d40b9c8 100644 --- a/src/signal/raise.c +++ b/src/signal/raise.c @@ -20,7 +20,7 @@ int raise(int sig) { SIGNAL_SAFE(0); if (__stdlib.exit_called == QUICK) { - __undefined("raise() called during quick_exit()"); + UNDEFINED("raise() called during quick_exit()"); } /* RETURN_FAILURE(NONZERO); diff --git a/src/stdarg/va_arg.c b/src/stdarg/va_arg.c index fd354ee8..2903682c 100644 --- a/src/stdarg/va_arg.c +++ b/src/stdarg/va_arg.c @@ -2,7 +2,7 @@ void va_arg() { - __undefined("The va_arg() macro has been suppressed to access an actual function"); + UNDEFINED("The va_arg() macro has been suppressed to access an actual function"); } /* diff --git a/src/stdarg/va_copy.c b/src/stdarg/va_copy.c index a2de7c7d..7cf817fd 100644 --- a/src/stdarg/va_copy.c +++ b/src/stdarg/va_copy.c @@ -2,7 +2,7 @@ void va_copy() { - __undefined("The va_copy() macro has been suppressed to access an actual function"); + UNDEFINED("The va_copy() macro has been suppressed to access an actual function"); } /* diff --git a/src/stdarg/va_end.c b/src/stdarg/va_end.c index 850c858b..073cd013 100644 --- a/src/stdarg/va_end.c +++ b/src/stdarg/va_end.c @@ -2,7 +2,7 @@ void va_end() { - __undefined("The va_end() macro has been suppressed to access an actual function"); + UNDEFINED("The va_end() macro has been suppressed to access an actual function"); } /* diff --git a/src/stdarg/va_start.c b/src/stdarg/va_start.c index 94a5fdb5..b648a11b 100644 --- a/src/stdarg/va_start.c +++ b/src/stdarg/va_start.c @@ -2,7 +2,7 @@ void va_start() { - __undefined("The va_start() macro has been suppressed to access an actual function"); + UNDEFINED("The va_start() macro has been suppressed to access an actual function"); } /* 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) { diff --git a/src/stdlib/_stdlib.h b/src/stdlib/_stdlib.h index 14953e6f..27054543 100644 --- a/src/stdlib/_stdlib.h +++ b/src/stdlib/_stdlib.h @@ -23,7 +23,7 @@ static int __safe_compar(int (*compar)(const void *, const void *), const void * unsigned int h2 = __hash(p2, size); int ret = compar(p1, p2); if (h1 != __hash(p1, size) || h2 != __hash(p2, size)) { - __undefined("In call to %s(): Comparison function modifies parameters", fn); + UNDEFINED("In call to %s(): Comparison function modifies parameters", fn); } return ret; } diff --git a/src/stdlib/bsearch.c b/src/stdlib/bsearch.c index a096cf16..f3b0fb32 100644 --- a/src/stdlib/bsearch.c +++ b/src/stdlib/bsearch.c @@ -21,7 +21,7 @@ void * bsearch(const void * key, const void * base, size_t nmemb, size_t size, i #ifndef NDEBUG for (size_t i = 0; nmemb != 0 && i < nmemb - 1; i++) { if (SAFE_COMPAR(compar, addr + (i * size), addr + ((i + 1) * size), size, "bsearch") > 0) { - __undefined("In call to bsearch(): Base array is not sorted"); + UNDEFINED("In call to bsearch(): Base array is not sorted"); } } #endif diff --git a/src/time/asctime.c b/src/time/asctime.c index f3d46fad..e3448347 100644 --- a/src/time/asctime.c +++ b/src/time/asctime.c @@ -4,7 +4,7 @@ #define CHECKRANGE(field, min, max) do {\ if (timeptr->tm_##field < min || timeptr->tm_##field > max) { \ - __undefined("In call to asctime(), the field tm_%s (%d) is out of range [%d, %d] in the provided time", #field, timeptr->tm_##field, min, max); \ + UNDEFINED("In call to asctime(), the field tm_%s (%d) is out of range [%d, %d] in the provided time", #field, timeptr->tm_##field, min, max); \ } \ } while (0) |