summaryrefslogtreecommitdiff
path: root/lib/mlibc/options/ansi/generic/stdio-stubs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mlibc/options/ansi/generic/stdio-stubs.cpp')
-rw-r--r--lib/mlibc/options/ansi/generic/stdio-stubs.cpp1270
1 files changed, 0 insertions, 1270 deletions
diff --git a/lib/mlibc/options/ansi/generic/stdio-stubs.cpp b/lib/mlibc/options/ansi/generic/stdio-stubs.cpp
deleted file mode 100644
index 479a655..0000000
--- a/lib/mlibc/options/ansi/generic/stdio-stubs.cpp
+++ /dev/null
@@ -1,1270 +0,0 @@
-#include <ctype.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <ctype.h>
-#include <limits.h>
-
-#include <abi-bits/fcntl.h>
-
-#include <bits/ensure.h>
-
-#include <mlibc/lock.hpp>
-#include <mlibc/allocator.hpp>
-#include <mlibc/debug.hpp>
-#include <mlibc/file-io.hpp>
-#include <mlibc/ansi-sysdeps.hpp>
-#include <frg/mutex.hpp>
-#include <frg/expected.hpp>
-#include <frg/printf.hpp>
-
-template<typename F>
-struct PrintfAgent {
- PrintfAgent(F *formatter, frg::va_struct *vsp)
- : _formatter{formatter}, _vsp{vsp} { }
-
- frg::expected<frg::format_error> operator() (char c) {
- _formatter->append(c);
- return {};
- }
- frg::expected<frg::format_error> operator() (const char *c, size_t n) {
- _formatter->append(c, n);
- return {};
- }
-
- frg::expected<frg::format_error> operator() (char t, frg::format_options opts,
- frg::printf_size_mod szmod) {
- switch(t) {
- case 'c':
- if (szmod == frg::printf_size_mod::long_size) {
- char c_buf[sizeof(wchar_t)];
- auto c = static_cast<wchar_t>(va_arg(_vsp->args, wint_t));
- mbstate_t shift_state = {};
- if (wcrtomb(c_buf, c, &shift_state) == size_t(-1))
- return frg::format_error::agent_error;
- _formatter->append(c_buf);
- break;
- }
- frg::do_printf_chars(*_formatter, t, opts, szmod, _vsp);
- break;
- case 'p': case 's':
- frg::do_printf_chars(*_formatter, t, opts, szmod, _vsp);
- break;
- case 'd': case 'i': case 'o': case 'x': case 'X': case 'u':
- frg::do_printf_ints(*_formatter, t, opts, szmod, _vsp);
- break;
- case 'f': case 'F': case 'g': case 'G': case 'e': case 'E':
- frg::do_printf_floats(*_formatter, t, opts, szmod, _vsp);
- break;
- case 'm':
- __ensure(!opts.fill_zeros);
- __ensure(!opts.left_justify);
- __ensure(!opts.alt_conversion);
- __ensure(opts.minimum_width == 0);
- __ensure(szmod == frg::printf_size_mod::default_size);
- __ensure(!opts.precision);
- _formatter->append(strerror(errno));
- break;
- case 'n': {
- __ensure(szmod == frg::printf_size_mod::default_size);
- auto p = va_arg(_vsp->args, int *);
- *p = _formatter->count;
- break;
- }
- default:
- mlibc::infoLogger() << "\e[31mmlibc: Unknown printf terminator '"
- << t << "'\e[39m" << frg::endlog;
- __ensure(!"Illegal printf terminator");
- }
-
- return {};
- }
-
-private:
- F *_formatter;
- frg::va_struct *_vsp;
-};
-
-struct StreamPrinter {
- StreamPrinter(FILE *stream)
- : stream(stream), count(0) { }
-
- void append(char c) {
- fwrite_unlocked(&c, 1, 1, stream);
- count++;
- }
-
- void append(const char *str) {
- fwrite_unlocked(str, strlen(str), 1, stream);
- count += strlen(str);
- }
-
- void append(const char *str, size_t n) {
- fwrite_unlocked(str, n, 1, stream);
- count += n;
- }
-
- FILE *stream;
- size_t count;
-};
-
-struct BufferPrinter {
- BufferPrinter(char *buffer)
- : buffer(buffer), count(0) { }
-
- void append(char c) {
- buffer[count] = c;
- count++;
- }
-
- void append(const char *str) {
- // TODO: use strcat
- for(size_t i = 0; str[i]; i++) {
- buffer[count] = str[i];
- count++;
- }
- }
-
- void append(const char *str, size_t n) {
- // TODO: use strcat
- for(size_t i = 0; i < n; i++) {
- buffer[count] = str[i];
- count++;
- }
- }
-
- char *buffer;
- size_t count;
-};
-
-struct LimitedPrinter {
- LimitedPrinter(char *buffer, size_t limit)
- : buffer(buffer), limit(limit), count(0) { }
-
- void append(char c) {
- if(count < limit)
- buffer[count] = c;
- count++;
- }
-
- void append(const char *str) {
- // TODO: use strcat
- for(size_t i = 0; str[i]; i++)
- append(str[i]);
- }
-
- void append(const char *str, size_t n) {
- // TODO: use strcat
- for(size_t i = 0; i < n; i++)
- append(str[i]);
- }
-
- char *buffer;
- size_t limit;
- size_t count;
-};
-
-struct ResizePrinter {
- ResizePrinter()
- : buffer(nullptr), limit(0), count(0) { }
-
- void expand() {
- if(count == limit) {
- auto new_limit = frg::max(2 * limit, size_t(16));
- auto new_buffer = reinterpret_cast<char *>(malloc(new_limit));
- __ensure(new_buffer);
- memcpy(new_buffer, buffer, count);
- free(buffer);
- buffer = new_buffer;
- limit = new_limit;
- }
- __ensure(count < limit);
- }
-
- void append(char c) {
- expand();
- buffer[count] = c;
- count++;
- }
-
- void append(const char *str) {
- for(size_t i = 0; str[i]; i++)
- append(str[i]);
- }
-
- void append(const char *str, size_t n) {
- for(size_t i = 0; i < n; i++)
- append(str[i]);
- }
-
- char *buffer;
- size_t limit;
- size_t count;
-};
-
-int remove(const char *filename) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_rmdir, -1);
- if(int e = mlibc::sys_rmdir(filename); e) {
- if (e == ENOTDIR) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_unlinkat, -1);
- if(e = mlibc::sys_unlinkat(AT_FDCWD, filename, 0); e) {
- errno = e;
- return -1;
- }
-
- return 0;
- }
- return -1;
- }
-
- return 0;
-}
-
-int rename(const char *path, const char *new_path) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_rename, -1);
- if(int e = mlibc::sys_rename(path, new_path); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int renameat(int olddirfd, const char *old_path, int newdirfd, const char *new_path) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_renameat, -1);
- if(int e = mlibc::sys_renameat(olddirfd, old_path, newdirfd, new_path); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-FILE *tmpfile(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-char *tmpnam(char *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-// fflush() is provided by the POSIX sublibrary
-// fopen() is provided by the POSIX sublibrary
-FILE *freopen(const char *__restrict path, const char *__restrict mode, FILE *__restrict f) {
- auto file = static_cast<mlibc::abstract_file *>(f);
- frg::unique_lock lock(file->_lock);
-
- if(file->reopen(path, mode) == -1) {
- errno = EINVAL;
- return nullptr;
- }
-
- return f;
-}
-
-void setbuf(FILE *__restrict stream, char *__restrict buffer) {
- setvbuf(stream, buffer, buffer ? _IOFBF : _IONBF, BUFSIZ);
-}
-// setvbuf() is provided by the POSIX sublibrary
-
-void setlinebuf(FILE *stream) {
- setvbuf(stream, NULL, _IOLBF, 0);
-}
-
-void setbuffer(FILE *f, char *buf, size_t size) {
- setvbuf(f, buf, buf ? _IOFBF : _IONBF, size);
-}
-
-int fprintf(FILE *__restrict stream, const char *__restrict format, ...) {
- va_list args;
- va_start(args, format);
- int result = vfprintf(stream, format, args);
- va_end(args);
- return result;
-}
-
-int fscanf(FILE *__restrict stream, const char *__restrict format, ...) {
- va_list args;
- va_start(args, format);
- int result = vfscanf(stream, format, args);
- va_end(args);
- return result;
-}
-
-int printf(const char *__restrict format, ...) {
- va_list args;
- va_start(args, format);
- int result = vfprintf(stdout, format, args);
- va_end(args);
- return result;
-}
-
-namespace {
- enum {
- SCANF_TYPE_CHAR,
- SCANF_TYPE_SHORT,
- SCANF_TYPE_INTMAX,
- SCANF_TYPE_L,
- SCANF_TYPE_LL,
- SCANF_TYPE_PTRDIFF,
- SCANF_TYPE_SIZE_T,
- SCANF_TYPE_INT
- };
-}
-
-static void store_int(void *dest, unsigned int size, unsigned long long i) {
- switch (size) {
- case SCANF_TYPE_CHAR:
- *(char *)dest = i;
- break;
- case SCANF_TYPE_SHORT:
- *(short *)dest = i;
- break;
- case SCANF_TYPE_INTMAX:
- *(intmax_t *)dest = i;
- break;
- case SCANF_TYPE_L:
- *(long *)dest = i;
- break;
- case SCANF_TYPE_LL:
- *(long long *)dest = i;
- break;
- case SCANF_TYPE_PTRDIFF:
- *(ptrdiff_t *)dest = i;
- break;
- case SCANF_TYPE_SIZE_T:
- *(size_t *)dest = i;
- break;
- /* fallthrough */
- case SCANF_TYPE_INT:
- default:
- *(int *)dest = i;
- break;
- }
-}
-
-template<typename H>
-static int do_scanf(H &handler, const char *fmt, __builtin_va_list args) {
- int match_count = 0;
- for (; *fmt; fmt++) {
-
- if (isspace(*fmt)) {
- while (isspace(fmt[1])) fmt++;
- while (isspace(handler.look_ahead()))
- handler.consume();
- continue;
- }
-
- if (*fmt != '%' || fmt[1] == '%') {
- if (*fmt == '%')
- fmt++;
- char c = handler.consume();
- if (c != *fmt)
- break;
- continue;
- }
-
- void *dest = NULL;
- /* %n$ format */
- if (isdigit(*fmt) && fmt[1] == '$') {
- /* TODO: dest = get_arg_at_pos(args, *fmt -'0'); */
- fmt += 3;
- } else {
- if (fmt[1] != '*') {
- dest = va_arg(args, void*);
- }
- fmt++;
- }
-
- int width = 0;
- if (*fmt == '*') {
- fmt++;
- } else if (*fmt == '\'') {
- /* TODO: numeric seperators locale stuff */
- mlibc::infoLogger() << "do_scanf: \' not implemented!" << frg::endlog;
- fmt++;
- continue;
- } else if (*fmt == 'm') {
- /* TODO: allocate buffer for them */
- mlibc::infoLogger() << "do_scanf: m not implemented!" << frg::endlog;
- fmt++;
- continue;
- } else if (*fmt >= '0' && *fmt <= '9') {
- /* read in width specifier */
- width = 0;
- while (*fmt >= '0' && *fmt <= '9') {
- width = width * 10 + (*fmt - '0');
- fmt++;
- continue;
- }
- }
-
- /* type modifiers */
- unsigned int type = SCANF_TYPE_INT;
- unsigned int base = 10;
- switch (*fmt) {
- case 'h': {
- if (fmt[1] == 'h') {
- type = SCANF_TYPE_CHAR;
- fmt += 2;
- break;
- }
- type = SCANF_TYPE_SHORT;
- fmt++;
- break;
- }
- case 'j': {
- type = SCANF_TYPE_INTMAX;
- fmt++;
- break;
- }
- case 'l': {
- if (fmt[1] == 'l') {
- type = SCANF_TYPE_LL;
- fmt += 2;
- break;
- }
- type = SCANF_TYPE_L;
- fmt++;
- break;
- }
- case 'L': {
- type = SCANF_TYPE_LL;
- fmt++;
- break;
- }
- case 'q': {
- type = SCANF_TYPE_LL;
- fmt++;
- break;
- }
- case 't': {
- type = SCANF_TYPE_PTRDIFF;
- fmt++;
- break;
- }
- case 'z': {
- type = SCANF_TYPE_SIZE_T;
- fmt++;
- break;
- }
- }
-
- // Leading whitespace is skipped for most conversions except these.
- if (*fmt != 'c' && *fmt != '[' && *fmt != 'n') {
- while (isspace(handler.look_ahead()))
- handler.consume();
- }
-
- switch (*fmt) {
- case 'd':
- case 'u':
- base = 10;
- [[fallthrough]];
- case 'i': {
- bool is_negative = false;
- unsigned long long res = 0;
-
- if((*fmt == 'i' || *fmt == 'd') && handler.look_ahead() == '-') {
- handler.consume();
- is_negative = true;
- }
-
- if(*fmt == 'i' && handler.look_ahead() == '0') {
- handler.consume();
- if(handler.look_ahead() == 'x') {
- handler.consume();
- base = 16;
- } else {
- base = 8;
- }
- }
-
- char c = handler.look_ahead();
- switch (base) {
- case 10:
- if(!isdigit(c))
- return match_count;
- while (c >= '0' && c <= '9') {
- handler.consume();
- res = res * 10 + (c - '0');
- c = handler.look_ahead();
- }
- break;
- case 16:
- if (c == '0') {
- handler.consume();
- c = handler.look_ahead();
- if (c == 'x') {
- handler.consume();
- c = handler.look_ahead();
- }
- }
- while (true) {
- if (c >= '0' && c <= '9') {
- handler.consume();
- res = res * 16 + (c - '0');
- } else if (c >= 'a' && c <= 'f') {
- handler.consume();
- res = res * 16 + (c - 'a' + 10);
- } else if (c >= 'A' && c <= 'F') {
- handler.consume();
- res = res * 16 + (c - 'A' + 10);
- } else {
- break;
- }
- c = handler.look_ahead();
- }
- break;
- case 8:
- while (c >= '0' && c <= '7') {
- handler.consume();
- res = res * 8 + (c - '0');
- c = handler.look_ahead();
- }
- break;
- }
- if (dest) {
- if(is_negative)
- store_int(dest, type, -res);
- else
- store_int(dest, type, res);
- }
- break;
- }
- case 'o': {
- unsigned long long res = 0;
- char c = handler.look_ahead();
- while (c >= '0' && c <= '7') {
- handler.consume();
- res = res * 8 + (c - '0');
- c = handler.look_ahead();
- }
- if (dest)
- store_int(dest, type, res);
- break;
- }
- case 'x':
- case 'X': {
- unsigned long long res = 0;
- char c = handler.look_ahead();
- if (c == '0') {
- handler.consume();
- c = handler.look_ahead();
- if (c == 'x') {
- handler.consume();
- c = handler.look_ahead();
- }
- }
- while (true) {
- if (c >= '0' && c <= '9') {
- handler.consume();
- res = res * 16 + (c - '0');
- } else if (c >= 'a' && c <= 'f') {
- handler.consume();
- res = res * 16 + (c - 'a' + 10);
- } else if (c >= 'A' && c <= 'F') {
- handler.consume();
- res = res * 16 + (c - 'A' + 10);
- } else {
- break;
- }
- c = handler.look_ahead();
- }
- if (dest)
- store_int(dest, type, res);
- break;
- }
- case 's': {
- char *typed_dest = (char *)dest;
- char c = handler.look_ahead();
- int count = 0;
- while (c && !isspace(c)) {
- handler.consume();
- if (typed_dest)
- typed_dest[count] = c;
- c = handler.look_ahead();
- count++;
- if (width && count >= width)
- break;
- }
- if (typed_dest)
- typed_dest[count] = '\0';
- break;
- }
- case 'c': {
- char *typed_dest = (char *)dest;
- char c = handler.look_ahead();
- int count = 0;
- if (!width)
- width = 1;
- while (c && count < width) {
- handler.consume();
- if (typed_dest)
- typed_dest[count] = c;
- c = handler.look_ahead();
- count++;
- }
- break;
- }
- case '[': {
- fmt++;
- int invert = 0;
- if (*fmt == '^') {
- invert = 1;
- fmt++;
- }
-
- char scanset[257];
- memset(&scanset[0], invert, sizeof(char) * 257);
- scanset[0] = '\0';
-
- if (*fmt == '-') {
- fmt++;
- scanset[1+'-'] = 1 - invert;
- } else if (*fmt == ']') {
- fmt++;
- scanset[1+']'] = 1 - invert;
- }
-
- for (; *fmt != ']'; fmt++) {
- if (!*fmt) return EOF;
- if (*fmt == '-' && *fmt != ']') {
- fmt++;
- for (char c = *(fmt - 2); c < *fmt; c++)
- scanset[1 + c] = 1 - invert;
- }
- scanset[1 + *fmt] = 1 - invert;
- }
-
- char *typed_dest = (char *)dest;
- int count = 0;
- char c = handler.look_ahead();
- while (c && (!width || count < width)) {
- handler.consume();
- if (!scanset[1 + c])
- break;
- if (typed_dest)
- typed_dest[count] = c;
- c = handler.look_ahead();
- count++;
- }
- if (typed_dest)
- typed_dest[count] = '\0';
- break;
- }
- case 'p': {
- unsigned long long res = 0;
- char c = handler.look_ahead();
- if (c == '0') {
- handler.consume();
- c = handler.look_ahead();
- if (c == 'x') {
- handler.consume();
- c = handler.look_ahead();
- }
- }
- while (true) {
- if (c >= '0' && c <= '9') {
- handler.consume();
- res = res * 16 + (c - '0');
- } else if (c >= 'a' && c <= 'f') {
- handler.consume();
- res = res * 16 + (c - 'a');
- } else if (c >= 'A' && c <= 'F') {
- handler.consume();
- res = res * 16 + (c - 'A');
- } else {
- break;
- }
- c = handler.look_ahead();
- }
- void **typed_dest = (void **)dest;
- *typed_dest = (void *)(uintptr_t)res;
- break;
- }
- case 'n': {
- int *typed_dest = (int *)dest;
- if (typed_dest)
- *typed_dest = handler.num_consumed;
- continue;
- }
- }
- if (dest) match_count++;
- }
- return match_count;
-}
-
-int scanf(const char *__restrict format, ...) {
- va_list args;
- va_start(args, format);
- int result = vfscanf(stdin, format, args);
- va_end(args);
- return result;
-}
-
-int snprintf(char *__restrict buffer, size_t max_size, const char *__restrict format, ...) {
- va_list args;
- va_start(args, format);
- int result = vsnprintf(buffer, max_size, format, args);
- va_end(args);
- return result;
-}
-
-int sprintf(char *__restrict buffer, const char *__restrict format, ...) {
- va_list args;
- va_start(args, format);
- int result = vsprintf(buffer, format, args);
- va_end(args);
- return result;
-}
-
-int sscanf(const char *__restrict buffer, const char *__restrict format, ...) {
- va_list args;
- va_start(args, format);
-
- int result = vsscanf(buffer, format, args);
-
- va_end(args);
- return result;
-}
-
-int vfprintf(FILE *__restrict stream, const char *__restrict format, __builtin_va_list args) {
- frg::va_struct vs;
- frg::arg arg_list[NL_ARGMAX + 1];
- vs.arg_list = arg_list;
- va_copy(vs.args, args);
- auto file = static_cast<mlibc::abstract_file *>(stream);
- frg::unique_lock lock(file->_lock);
- StreamPrinter p{stream};
-// mlibc::infoLogger() << "printf(" << format << ")" << frg::endlog;
- auto res = frg::printf_format(PrintfAgent{&p, &vs}, format, &vs);
- if (!res)
- return -static_cast<int>(res.error());
-
- return p.count;
-}
-
-int vfscanf(FILE *__restrict stream, const char *__restrict format, __builtin_va_list args) {
- auto file = static_cast<mlibc::abstract_file *>(stream);
- frg::unique_lock lock(file->_lock);
-
- struct {
- char look_ahead() {
- char c;
- size_t actual_size;
- file->read(&c, 1, &actual_size);
- if (actual_size)
- file->unget(c);
- return actual_size ? c : 0;
- }
-
- char consume() {
- char c;
- size_t actual_size;
- file->read(&c, 1, &actual_size);
- if (actual_size)
- num_consumed++;
- return actual_size ? c : 0;
- }
-
- mlibc::abstract_file *file;
- int num_consumed;
- } handler = {file, 0};
-
- return do_scanf(handler, format, args);
-}
-
-int vprintf(const char *__restrict format, __builtin_va_list args){
- return vfprintf(stdout, format, args);
-}
-
-int vscanf(const char *__restrict, __builtin_va_list) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int vsnprintf(char *__restrict buffer, size_t max_size,
- const char *__restrict format, __builtin_va_list args) {
- frg::va_struct vs;
- frg::arg arg_list[NL_ARGMAX + 1];
- vs.arg_list = arg_list;
- va_copy(vs.args, args);
- LimitedPrinter p{buffer, max_size ? max_size - 1 : 0};
-// mlibc::infoLogger() << "printf(" << format << ")" << frg::endlog;
- auto res = frg::printf_format(PrintfAgent{&p, &vs}, format, &vs);
- if (!res)
- return -static_cast<int>(res.error());
- if (max_size)
- p.buffer[frg::min(max_size - 1, p.count)] = 0;
- return p.count;
-}
-
-int vsprintf(char *__restrict buffer, const char *__restrict format, __builtin_va_list args) {
- frg::va_struct vs;
- frg::arg arg_list[NL_ARGMAX + 1];
- vs.arg_list = arg_list;
- va_copy(vs.args, args);
- BufferPrinter p(buffer);
-// mlibc::infoLogger() << "printf(" << format << ")" << frg::endlog;
- auto res = frg::printf_format(PrintfAgent{&p, &vs}, format, &vs);
- if (!res)
- return -static_cast<int>(res.error());
- p.buffer[p.count] = 0;
- return p.count;
-}
-
-int vsscanf(const char *__restrict buffer, const char *__restrict format, __builtin_va_list args) {
- struct {
- char look_ahead() {
- return *buffer;
- }
-
- char consume() {
- num_consumed++;
- return *buffer++;
- }
-
- const char *buffer;
- int num_consumed;
- } handler = {buffer, 0};
-
- int result = do_scanf(handler, format, args);
-
- return result;
-}
-
-int fwprintf(FILE *__restrict, const wchar_t *__restrict, ...) MLIBC_STUB_BODY
-int fwscanf(FILE *__restrict, const wchar_t *__restrict, ...) MLIBC_STUB_BODY
-int vfwprintf(FILE *__restrict, const wchar_t *__restrict, __builtin_va_list) MLIBC_STUB_BODY
-int vfwscanf(FILE *__restrict, const wchar_t *__restrict, __builtin_va_list) MLIBC_STUB_BODY
-
-int swprintf(wchar_t *__restrict, size_t, const wchar_t *__restrict, ...) MLIBC_STUB_BODY
-int swscanf(wchar_t *__restrict, size_t, const wchar_t *__restrict, ...) MLIBC_STUB_BODY
-int vswprintf(wchar_t *__restrict, size_t, const wchar_t *__restrict, __builtin_va_list) MLIBC_STUB_BODY
-int vswscanf(wchar_t *__restrict, size_t, const wchar_t *__restrict, __builtin_va_list) MLIBC_STUB_BODY
-
-int wprintf(const wchar_t *__restrict, ...) MLIBC_STUB_BODY
-int wscanf(const wchar_t *__restrict, ...) MLIBC_STUB_BODY
-int vwprintf(const wchar_t *__restrict, __builtin_va_list) MLIBC_STUB_BODY
-int vwscanf(const wchar_t *__restrict, __builtin_va_list) MLIBC_STUB_BODY
-
-int fgetc(FILE *stream) {
- char c;
- auto bytes_read = fread(&c, 1, 1, stream);
- if(bytes_read != 1)
- return EOF;
- return c;
-}
-
-char *fgets(char *__restrict buffer, size_t max_size, FILE *__restrict stream) {
- auto file = static_cast<mlibc::abstract_file *>(stream);
- frg::unique_lock lock(file->_lock);
- return fgets_unlocked(buffer, max_size, stream);
-}
-
-int fputc_unlocked(int c, FILE *stream) {
- char d = c;
- if(fwrite_unlocked(&d, 1, 1, stream) != 1)
- return EOF;
- return 1;
-}
-
-int fputc(int c, FILE *stream) {
- auto file = static_cast<mlibc::abstract_file *>(stream);
- frg::unique_lock lock(file->_lock);
- return fputc_unlocked(c, stream);
-}
-
-int fputs_unlocked(const char *__restrict string, FILE *__restrict stream) {
- if(fwrite_unlocked(string, strlen(string), 1, stream) != 1)
- return EOF;
- return 1;
-}
-
-int fputs(const char *__restrict string, FILE *__restrict stream) {
- auto file = static_cast<mlibc::abstract_file *>(stream);
- frg::unique_lock lock(file->_lock);
- return fputs_unlocked(string, stream);
-}
-
-int getc_unlocked(FILE *stream) {
- return fgetc_unlocked(stream);
-}
-
-int getc(FILE *stream) {
- return fgetc(stream);
-}
-
-int getchar_unlocked(void) {
- return fgetc_unlocked(stdin);
-}
-
-int getchar(void) {
- return fgetc(stdin);
-}
-
-char *gets(char *s){
- return fgets(s, SIZE_MAX, stdin);
-}
-
-int putc_unlocked(int c, FILE *stream) {
- char d = c;
- if(fwrite_unlocked(&d, 1, 1, stream) != 1)
- return EOF;
- return c;
-}
-
-int putc(int c, FILE *stream) {
- auto file = static_cast<mlibc::abstract_file *>(stream);
- frg::unique_lock lock(file->_lock);
- return putc_unlocked(c, stream);
-}
-
-int putchar_unlocked(int c) {
- return putc_unlocked(c, stdout);
-}
-
-int putchar(int c) {
- auto file = static_cast<mlibc::abstract_file *>(stdout);
- frg::unique_lock lock(file->_lock);
- return putchar_unlocked(c);
-}
-
-int puts(const char *string) {
- auto file = static_cast<mlibc::abstract_file *>(stdout);
- frg::unique_lock lock(file->_lock);
-
- size_t progress = 0;
- size_t len = strlen(string);
- while(progress < len) {
- size_t chunk;
- if(file->write(string + progress,
- len - progress, &chunk)) {
- return EOF;
- }else if(!chunk) {
- return EOF;
- }
-
- progress += chunk;
- }
-
- size_t unused;
- if (!file->write("\n", 1, &unused)) {
- return EOF;
- }
-
- return 1;
-}
-
-wint_t fgetwc(FILE *) MLIBC_STUB_BODY
-wchar_t *fgetws(wchar_t *__restrict, int, FILE *__restrict) MLIBC_STUB_BODY
-wint_t fputwc(wchar_t, FILE *) MLIBC_STUB_BODY
-int fputws(const wchar_t *__restrict, FILE *__restrict) MLIBC_STUB_BODY
-int fwide(FILE *, int) MLIBC_STUB_BODY
-wint_t getwc(FILE *) MLIBC_STUB_BODY
-wint_t getwchar(void) MLIBC_STUB_BODY
-wint_t putwc(wchar_t, FILE *) MLIBC_STUB_BODY
-wint_t putwchar(wchar_t) MLIBC_STUB_BODY
-wint_t ungetwc(wint_t, FILE *) MLIBC_STUB_BODY
-
-size_t fread(void *buffer, size_t size, size_t count, FILE *file_base) {
- auto file = static_cast<mlibc::abstract_file *>(file_base);
- frg::unique_lock lock(file->_lock);
- return fread_unlocked(buffer, size, count, file_base);
-}
-
-size_t fwrite(const void *buffer, size_t size , size_t count, FILE *file_base) {
- auto file = static_cast<mlibc::abstract_file *>(file_base);
- frg::unique_lock lock(file->_lock);
- return fwrite_unlocked(buffer, size, count, file_base);
-}
-
-int fgetpos(FILE *__restrict, fpos_t *__restrict) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-// fseek() is provided by the POSIX sublibrary
-int fsetpos(FILE *, const fpos_t *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-// ftell() is provided by the POSIX sublibrary
-
-void clearerr(FILE *file_base) {
- file_base->__status_bits = 0;
-}
-
-int feof(FILE *file_base) {
- return file_base->__status_bits & __MLIBC_EOF_BIT;
-}
-
-int ferror(FILE *file_base) {
- return file_base->__status_bits & __MLIBC_ERROR_BIT;
-}
-
-void perror(const char *string) {
- int error = errno;
- if (string && *string) {
- fprintf(stderr, "%s: ", string);
- }
- fprintf(stderr, "%s\n", strerror(error));
-}
-
-// POSIX extensions.
-
-ssize_t getline(char **line, size_t *n, FILE *stream) {
- return getdelim(line, n, '\n', stream);
-}
-
-ssize_t getdelim(char **line, size_t *n, int delim, FILE *stream) {
- // Otherwise, we cannot store the buffer / size.
- if(!line || !n) {
- errno = EINVAL;
- return -1;
- }
-
- char *buffer = *line;
- /* set the starting capacity to 512 if buffer = NULL */
- size_t capacity = (!buffer) ? 512 : *n;
- size_t nwritten = 0;
-
- auto file = static_cast<mlibc::abstract_file *>(stream);
- frg::unique_lock lock(file->_lock);
-
- // Avoid allocating if we've already hit the end
- auto c = fgetc_unlocked(stream);
- if (c == EOF || ferror(stream)) {
- return -1;
- } else {
- file->unget(c);
- }
-
- while (true) {
- // Fill the buffer
- while (buffer && capacity > 0 && nwritten < capacity - 1) {
- auto c = fgetc_unlocked(stream);
- if (ferror(stream)) {
- return -1;
- } else if (c == EOF) {
- buffer[nwritten] = 0;
- return nwritten;
- }
-
- buffer[nwritten++] = c;
-
- if (c == delim) {
- buffer[nwritten] = 0;
- return nwritten;
- }
- }
-
- // Double the size of the buffer (but make sure it's at least 1024)
- capacity = (capacity >= 1024) ? capacity * 2 : 1024;
- buffer = reinterpret_cast<char *>(getAllocator().reallocate(*line, capacity));
- if (!buffer) {
- errno = ENOMEM;
- return -1;
- }
-
- *line = buffer;
- *n = capacity;
- }
-}
-
-// GLIBC extensions.
-
-int asprintf(char **out, const char *format, ...) {
- va_list args;
- va_start(args, format);
- int result = vasprintf(out, format, args);
- va_end(args);
- return result;
-}
-
-int vasprintf(char **out, const char *format, __builtin_va_list args) {
- frg::va_struct vs;
- frg::arg arg_list[NL_ARGMAX + 1];
- vs.arg_list = arg_list;
- va_copy(vs.args, args);
- ResizePrinter p;
-// mlibc::infoLogger() << "printf(" << format << ")" << frg::endlog;
- auto res = frg::printf_format(PrintfAgent{&p, &vs}, format, &vs);
- if (!res)
- return -static_cast<int>(res.error());
- p.expand();
- p.buffer[p.count] = 0;
- *out = p.buffer;
- return p.count;
-}
-
-// Linux unlocked I/O extensions.
-
-void flockfile(FILE *file_base) {
- static_cast<mlibc::abstract_file *>(file_base)->_lock.lock();
-}
-
-void funlockfile(FILE *file_base) {
- static_cast<mlibc::abstract_file *>(file_base)->_lock.unlock();
-}
-
-int ftrylockfile(FILE *file_base) {
- static_cast<mlibc::abstract_file *>(file_base)->_lock.try_lock();
- return 0;
-}
-
-void clearerr_unlocked(FILE *file_base) {
- file_base->__status_bits = 0;
-}
-
-int feof_unlocked(FILE *file_base) {
- return file_base->__status_bits & __MLIBC_EOF_BIT;
-}
-
-int ferror_unlocked(FILE *file_base) {
- return file_base->__status_bits & __MLIBC_ERROR_BIT;
-}
-
-int fgetc_unlocked(FILE *stream) {
- unsigned char d;
- if(fread_unlocked(&d, 1, 1, stream) != 1)
- return EOF;
- return (int)d;
-}
-
-size_t fread_unlocked(void *buffer, size_t size, size_t count, FILE *file_base) {
- auto file = static_cast<mlibc::abstract_file *>(file_base);
- if(!size || !count)
- return 0;
-
- // Distinguish two cases here: If the object size is one, we perform byte-wise reads.
- // Otherwise, we try to read each object individually.
- if(size == 1) {
- size_t progress = 0;
- while(progress < count) {
- size_t chunk;
- if(int e = file->read((char *)buffer + progress,
- count - progress, &chunk)) {
- errno = e;
- return 0;
- }else if(!chunk) {
- // TODO: Handle eof.
- break;
- }
-
- progress += chunk;
- }
-
- return progress;
- }else{
- for(size_t i = 0; i < count; i++) {
- size_t progress = 0;
- while(progress < size) {
- size_t chunk;
- if(int e = file->read((char *)buffer + i * size + progress,
- size - progress, &chunk)) {
- errno = e;
- return 0;
- }else if(!chunk) {
- // TODO: Handle eof.
- break;
- }
-
- progress += chunk;
- }
-
- if(progress < size)
- return i;
- }
-
- return count;
- }
-}
-
-size_t fwrite_unlocked(const void *buffer, size_t size, size_t count, FILE *file_base) {
- auto file = static_cast<mlibc::abstract_file *>(file_base);
- if(!size || !count)
- return 0;
-
- // Distinguish two cases here: If the object size is one, we perform byte-wise writes.
- // Otherwise, we try to write each object individually.
- if(size == 1) {
- size_t progress = 0;
- while(progress < count) {
- size_t chunk;
- if(file->write((const char *)buffer + progress,
- count - progress, &chunk)) {
- // TODO: Handle I/O errors.
- mlibc::infoLogger() << "mlibc: fwrite() I/O errors are not handled"
- << frg::endlog;
- break;
- }else if(!chunk) {
- // TODO: Handle eof.
- break;
- }
-
- progress += chunk;
- }
-
- return progress;
- }else{
- for(size_t i = 0; i < count; i++) {
- size_t progress = 0;
- while(progress < size) {
- size_t chunk;
- if(file->write((const char *)buffer + i * size + progress,
- size - progress, &chunk)) {
- // TODO: Handle I/O errors.
- mlibc::infoLogger() << "mlibc: fwrite() I/O errors are not handled"
- << frg::endlog;
- break;
- }else if(!chunk) {
- // TODO: Handle eof.
- break;
- }
-
- progress += chunk;
- }
-
- if(progress < size)
- return i;
- }
-
- return count;
- }
-}
-
-char *fgets_unlocked(char *__restrict buffer, int max_size, FILE *stream) {
- __ensure(max_size > 0);
- for(int i = 0; ; i++) {
- if(i == max_size - 1) {
- buffer[i] = 0;
- return buffer;
- }
-
- auto c = fgetc_unlocked(stream);
-
- // If fgetc() fails, there is either an EOF or an I/O error.
- if(c == EOF) {
- if(i) {
- buffer[i] = 0;
- return buffer;
- } else {
- // In this case, the buffer is not changed.
- return nullptr;
- }
- } else {
- buffer[i] = c;
- }
-
- if(c == '\n') {
- buffer[i + 1] = 0;
- return buffer;
- }
- }
-}