summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2024-02-02 13:56:33 -0500
committerJakob Kaivo <jkk@ung.org>2024-02-02 13:56:33 -0500
commit8b3f2fa09e9241e20926c8171753a271c21ec93d (patch)
treea8bdff34505bfcf999467053dbfbf276bf7233f1
parent3a9026cf8557c8efec34e652b6bf37ce49f12f86 (diff)
first cut of tracking previous return values with ftell()/fseek() as POC
-rw-r--r--src/_safety.h25
-rw-r--r--src/stdio/_stdio.h7
-rw-r--r--src/stdio/freopen.c6
-rw-r--r--src/stdio/fseek.c3
-rw-r--r--src/stdio/ftell.c12
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;
}
/***