diff options
author | Jakob Kaivo <jkk@ung.org> | 2024-02-02 13:56:33 -0500 |
---|---|---|
committer | Jakob Kaivo <jkk@ung.org> | 2024-02-02 13:56:33 -0500 |
commit | 8b3f2fa09e9241e20926c8171753a271c21ec93d (patch) | |
tree | a8bdff34505bfcf999467053dbfbf276bf7233f1 | |
parent | 3a9026cf8557c8efec34e652b6bf37ce49f12f86 (diff) |
first cut of tracking previous return values with ftell()/fseek() as POC
-rw-r--r-- | src/_safety.h | 25 | ||||
-rw-r--r-- | src/stdio/_stdio.h | 7 | ||||
-rw-r--r-- | src/stdio/freopen.c | 6 | ||||
-rw-r--r-- | src/stdio/fseek.c | 3 | ||||
-rw-r--r-- | src/stdio/ftell.c | 12 |
5 files changed, 47 insertions, 6 deletions
diff --git a/src/_safety.h b/src/_safety.h index 37b66915..85637013 100644 --- a/src/_safety.h +++ b/src/_safety.h @@ -4,6 +4,7 @@ _Noreturn void __undefined(const char *, ...); #include <errno.h> +#include <stdlib.h> #include <stdio.h> /* #include "stdlib/_stdlib.h" @@ -28,6 +29,30 @@ extern struct __checked_call { #ifndef NDEBUG #define UNDEFINED(...) __undefined(__VA_ARGS__) +#define ADD_PREV(__val, __arr, __count) do { \ + void *tmp = realloc((__arr), ((__count) + 1) * sizeof((__arr)[0])); \ + if (tmp == NULL) { \ + fprintf(stderr, "Out of memory tracking values\n"); \ + abort(); \ + } \ + (__arr) = tmp; \ + (__arr)[__count] = __val; \ + (__count)++; \ +} while (0) + +#define ASSERT_PREV(__val, __arr, __count, __prev) do { \ + int __found = 0; \ + for (size_t __i = 0; __i < (__count); __i++) { \ + if ((__arr)[__i] == (__val)) { \ + __found = 1; \ + break; \ + } \ + } \ + if (!__found) { \ + UNDEFINED("In call to %s(): %s was not returned by a previous call to %s", __func__, #__val, __prev); \ + } \ +} while (0) + #define ASSERT_NONNULL(__ptr) do { \ if (!__ptr) { \ UNDEFINED("In call to %s(), parameter %s cannot be NULL", __func__, #__ptr); \ diff --git a/src/stdio/_stdio.h b/src/stdio/_stdio.h index d47ac5dd..c69b3787 100644 --- a/src/stdio/_stdio.h +++ b/src/stdio/_stdio.h @@ -59,7 +59,7 @@ struct __FILE { 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 operation:2; /* 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? */ @@ -67,6 +67,11 @@ struct __FILE { #ifdef _POSIX_C_SOURCE pid_t pipe_pid; /* if stream is a pipe, the child pid */ #endif + + fpos_t *valid_fpos; + size_t nvalid_fpos; + long int *valid_ftell; + size_t nvalid_ftell; }; struct io_options { diff --git a/src/stdio/freopen.c b/src/stdio/freopen.c index 3a1ef656..d431b0e3 100644 --- a/src/stdio/freopen.c +++ b/src/stdio/freopen.c @@ -96,6 +96,12 @@ FILE * freopen(const char * restrict filename, const char * restrict mode, FILE stream->buf = stream->ibuf; } + free(stream->valid_fpos); + stream->nvalid_fpos = 0; + + free(stream->valid_ftell); + stream->nvalid_ftell = 0; + stream->text = !(strchr(mode, 'b')); /* diff --git a/src/stdio/fseek.c b/src/stdio/fseek.c index 47388c9a..9f4bd733 100644 --- a/src/stdio/fseek.c +++ b/src/stdio/fseek.c @@ -12,8 +12,7 @@ int fseek(FILE *stream, long int offset, int whence) 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()"); */ + ASSERT_PREV(offset, stream->valid_ftell, stream->nvalid_ftell, "ftell"); } if (whence == SEEK_CUR) { diff --git a/src/stdio/ftell.c b/src/stdio/ftell.c index f68c18b2..ad23bf31 100644 --- a/src/stdio/ftell.c +++ b/src/stdio/ftell.c @@ -5,15 +5,21 @@ long int ftell(FILE *stream) { + long int ret = -1L; + SIGNAL_SAFE(0); + ASSERT_STREAM(stream, 0, 0); - (void)stream; - /* TODO */ /* RETURN_SUCCESS(the current file position); RETURN_FAILURE(LITERAL(-1L)); */ - return -1L; + + if (stream->text) { + ADD_PREV(ret, stream->valid_ftell, stream->nvalid_ftell); + } + + return ret; } /*** |