#include "printf.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#ifdef AX_CONFIG_MULTITASK
#include <pthread.h>
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
#endif
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
FILE __stdin_FILE = {.fd = 0, .buffer_len = 0};
FILE __stdout_FILE = {.fd = 1, .buffer_len = 0};
FILE __stderr_FILE = {.fd = 2, .buffer_len = 0};
FILE *const stdin = &__stdin_FILE;
FILE *const stdout = &__stdout_FILE;
FILE *const stderr = &__stderr_FILE;
static int __write_buffer(FILE *f)
{
int r = 0;
if (f->buffer_len == 0)
return 0;
r = write(f->fd, f->buf, f->buffer_len);
return r;
}
static void __clear_buffer(FILE *f)
{
f->buffer_len = 0;
}
static int __fflush(FILE *f)
{
int r = __write_buffer(f);
__clear_buffer(f);
return r >= 0 ? 0 : r;
}
static int out(FILE *f, const char *s, size_t l)
{
int ret = 0;
for (size_t i = 0; i < l; i++) {
char c = s[i];
f->buf[f->buffer_len++] = c;
if (f->buffer_len == FILE_BUF_SIZE || c == '\n') {
int r = __write_buffer(f);
__clear_buffer(f);
if (r < 0)
return r;
if (r < f->buffer_len)
return ret + r;
ret += r;
}
}
return ret;
}
int getchar(void)
{
unimplemented();
return 0;
}
int fflush(FILE *f)
{
return __fflush(f);
}
static inline int do_putc(int c, FILE *f)
{
char byte = c;
return out(f, &byte, 1);
}
int fputc(int c, FILE *f)
{
return do_putc(c, f);
}
int putc(int c, FILE *f)
{
return do_putc(c, f);
}
int putchar(int c)
{
return do_putc(c, stdout);
}
int puts(const char *s)
{
#ifdef AX_CONFIG_MULTITASK
pthread_mutex_lock(&lock);
#endif
int r = write(1, (const void *)s, strlen(s));
char brk[1] = {'\n'};
write(1, (const void *)brk, 1);
#ifdef AX_CONFIG_MULTITASK
pthread_mutex_unlock(&lock);
#endif
return r;
}
void perror(const char *msg)
{
FILE *f = stderr;
char *errstr = strerror(errno);
if (msg && *msg) {
out(f, msg, strlen(msg));
out(f, ": ", 2);
}
out(f, errstr, strlen(errstr));
out(f, "\n", 1);
}
static void __out_wrapper(char c, void *arg)
{
out(arg, &c, 1);
}
int printf(const char *restrict fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = vfprintf(stdout, fmt, ap);
va_end(ap);
return ret;
}
int fprintf(FILE *restrict f, const char *restrict fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = vfprintf(f, fmt, ap);
va_end(ap);
return ret;
}
int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap)
{
return vfctprintf(__out_wrapper, f, fmt, ap);
}
int sscanf(const char *restrict __s, const char *restrict __format, ...)
{
unimplemented();
return 0;
}
#ifdef AX_CONFIG_FS
int __fmodeflags(const char *mode)
{
int flags;
if (strchr(mode, '+'))
flags = O_RDWR;
else if (*mode == 'r')
flags = O_RDONLY;
else
flags = O_WRONLY;
if (strchr(mode, 'x'))
flags |= O_EXCL;
if (strchr(mode, 'e'))
flags |= O_CLOEXEC;
if (*mode != 'r')
flags |= O_CREAT;
if (*mode == 'w')
flags |= O_TRUNC;
if (*mode == 'a')
flags |= O_APPEND;
return flags;
}
FILE *fopen(const char *filename, const char *mode)
{
FILE *f;
int flags;
if (!strchr("rwa", *mode)) {
errno = EINVAL;
return 0;
}
f = (FILE *)malloc(sizeof(FILE));
flags = __fmodeflags(mode);
int fd = open(filename, flags, 0666);
if (fd < 0)
return NULL;
f->fd = fd;
return f;
}
char *fgets(char *restrict s, int n, FILE *restrict f)
{
if (n == 0)
return NULL;
if (n == 1) {
*s = '\0';
return s;
}
int cnt = 0;
while (cnt < n - 1) {
char c;
if (read(f->fd, (void *)&c, 1) > 0) {
if (c != '\n')
s[cnt++] = c;
else
break;
} else
break;
}
s[cnt] = '\0';
return s;
}
size_t fread(void *restrict destv, size_t size, size_t nmemb, FILE *restrict f)
{
size_t total = size * nmemb;
size_t read_len = 0;
size_t len = 0;
do {
len = read(f->fd, destv + read_len, total - read_len);
if (len < 0)
break;
read_len += len;
} while (len > 0);
return read_len == size * nmemb ? nmemb : read_len / size;
}
size_t fwrite(const void *restrict src, size_t size, size_t nmemb, FILE *restrict f)
{
size_t total = size * nmemb;
size_t write_len = 0;
size_t len = 0;
do {
len = write(f->fd, src + write_len, total - write_len);
if (len < 0)
break;
write_len += len;
} while (len > 0);
return write_len == size * nmemb ? nmemb : write_len / size;
}
int fputs(const char *restrict s, FILE *restrict f)
{
size_t l = strlen(s);
return (fwrite(s, 1, l, f) == l) - 1;
}
int fclose(FILE *f)
{
return close(f->fd);
}
int fileno(FILE *f)
{
return f->fd;
}
int feof(FILE *f)
{
unimplemented();
return 0;
}
int fseek(FILE *__stream, long __off, int __whence)
{
unimplemented();
return 0;
}
off_t ftello(FILE *__stream)
{
unimplemented();
return 0;
}
char *tmpnam(char *buf)
{
unimplemented();
return 0;
}
void clearerr(FILE *f)
{
unimplemented();
}
int ferror(FILE *f)
{
unimplemented();
return 0;
}
FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *restrict f)
{
unimplemented();
return 0;
}
int fscanf(FILE *restrict f, const char *restrict fmt, ...)
{
unimplemented();
return 0;
}
long ftell(FILE *f)
{
unimplemented();
return 0;
}
int getc(FILE *f)
{
unimplemented();
return 0;
}
int remove(const char *path)
{
unimplemented();
return 0;
}
int setvbuf(FILE *restrict f, char *restrict buf, int type, size_t size)
{
unimplemented();
return 0;
}
FILE *tmpfile(void)
{
unimplemented();
return NULL;
}
int ungetc(int c, FILE *f)
{
unimplemented();
return 0;
}
ssize_t getdelim(char **restrict s, size_t *restrict n, int delim, FILE *restrict f)
{
unimplemented();
return 0;
}
ssize_t getline(char **restrict s, size_t *restrict n, FILE *restrict f)
{
return getdelim(s, n, '\n', f);
}
int __uflow(FILE *f)
{
unimplemented();
return 0;
}
int getc_unlocked(FILE *f)
{
unimplemented();
return 0;
}
FILE *fdopen(int fd, const char *mode)
{
unimplemented();
return NULL;
}
#endif