summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2024-02-02 13:25:45 -0500
committerJakob Kaivo <jkk@ung.org>2024-02-02 13:25:45 -0500
commit24f39222098253da4ad1a9cd8ddef5b9b0152ba1 (patch)
tree36eede312e7dcb4a9afe49342fba996ef273549d
parent6aebe0dbfc24f0af73eb422b4748a9b35df5b435 (diff)
use UNDEFINED() instead of directly calling __undefined()
-rw-r--r--src/_safety.h6
-rw-r--r--src/assert/assert.c2
-rw-r--r--src/ctype/_ctype.h2
-rw-r--r--src/fenv/_fenv.h2
-rw-r--r--src/signal/__signal_handler.c4
-rw-r--r--src/signal/raise.c2
-rw-r--r--src/stdarg/va_arg.c2
-rw-r--r--src/stdarg/va_copy.c2
-rw-r--r--src/stdarg/va_end.c2
-rw-r--r--src/stdarg/va_start.c2
-rw-r--r--src/stdio/__printf.c44
-rw-r--r--src/stdio/_stdio.h28
-rw-r--r--src/stdio/clearerr.c2
-rw-r--r--src/stdio/feof.c3
-rw-r--r--src/stdio/ferror.c2
-rw-r--r--src/stdio/fgetc.c3
-rw-r--r--src/stdio/freopen.c4
-rw-r--r--src/stdio/fseek.c11
-rw-r--r--src/stdlib/_stdlib.h2
-rw-r--r--src/stdlib/bsearch.c2
-rw-r--r--src/time/asctime.c2
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)