summaryrefslogtreecommitdiff
path: root/src/stdio/_format.h
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2024-06-07 14:50:18 -0400
committerJakob Kaivo <jkk@ung.org>2024-06-07 14:50:18 -0400
commitfd466889b49dfe528567587183c2aedd27836f27 (patch)
tree02802cd3785b46a627530427d0e8774742754a7a /src/stdio/_format.h
parentc195cb021ead7de765a0b37f5ab793802be46731 (diff)
split formatted I/O header, unify undefined behavior reporting with UNDEFINED_FMT() macro
Diffstat (limited to 'src/stdio/_format.h')
-rw-r--r--src/stdio/_format.h82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/stdio/_format.h b/src/stdio/_format.h
new file mode 100644
index 00000000..5930fdb6
--- /dev/null
+++ b/src/stdio/_format.h
@@ -0,0 +1,82 @@
+#ifndef __STDIO__FORMAT_H__
+#define __STDIO__FORMAT_H__
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include "_stdio.h"
+#include "_safety.h"
+
+#define UNDEFINED_FMT(__conv, __fmt, ...) do { \
+ char __buf[128]; \
+ snprintf(__buf, sizeof(__buf), "In call to %s() with format string \"%s\": Invalid conversion specification: ", __conv->func, __conv->fmt); \
+ __undefined("%s" __fmt, __buf, __VA_ARGS__); \
+} while (0)
+
+struct io_options {
+ const char *fnname; /* the calling function */
+ char *string; /* NULL or the output string */
+ wchar_t *wstring; /* NULL or the output wide string */
+ FILE *stream; /* NULL or the output stream */
+ int fd; /* -1 or the output file descriptor */
+ size_t maxlen; /* max number of bytes to write to string */
+ size_t pos; /* current index in string */
+ int ret; /* return value */
+};
+
+struct io_conversion {
+ const char *func;
+ const char *fmt;
+ enum { IO_IN, IO_OUT } dir;
+ enum conversion_flags {
+ /* explicit */
+ F_STAR = (1<<0),
+ F_LEFT = (1<<1),
+ F_SIGN = (1<<2),
+ F_SPACE = (1<<3),
+ F_ALT = (1<<4),
+ F_ZERO = (1<<5),
+
+ /* inferred */
+ F_UPPER = (1<<10),
+ F_WIDTH = (1<<11),
+ F_PRECISION = (1<<12),
+ } flags;
+ enum conversion_length {
+ L_default,
+ L_hh,
+ L_ll,
+ L_h,
+ L_l,
+ L_j,
+ L_z,
+ L_t,
+ L_L,
+ } length;
+ uintmax_t width;
+ uintmax_t precision;
+ char spec;
+ union {
+ uintmax_t u;
+ intmax_t i;
+ float f;
+ double d;
+ long double ld;
+ char *s;
+ wchar_t *wcs;
+ char c;
+ wchar_t wc;
+ void *ptr;
+ } val;
+};
+
+size_t __conv(const char *, struct io_conversion *, va_list);
+int __printf(struct io_options * restrict, const char * restrict, va_list);
+int __scanf(struct io_options * restrict, const char * restrict, va_list);
+
+/*
+STDC(-1)
+*/
+
+#endif