olibc/src/stdio.c

214 lines
4.2 KiB
C

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#define O_RDWR 2 // FIXME
#define O_RDONLY 0
#define O_CREAT 64
#define O_TRUNC 512
#define O_WRONLY 1
#define O_APPEND 1024
#define EINVAL 22 // FIXME
FILE* fopen(const char *restrict pathname, const char *restrict mode) { // FIXME
if (pathname == NULL)
return (FILE*)NULL;
int oflag;
switch(mode[0]) { // TODO: add b and x mode (check C11 specifications)
case 'r':
if (strlen(mode) > 1 && mode[1] == '+')
oflag = O_RDWR;
else
oflag = O_RDONLY;
break;
case 'w':
if (strlen(mode) > 1 && mode[1] == '+')
oflag = O_RDWR | O_CREAT | O_TRUNC;
else
oflag = O_WRONLY | O_CREAT | O_TRUNC;
break;
case 'a':
if (strlen(mode) > 1 && mode[1] == '+')
oflag = O_RDWR | O_CREAT | O_APPEND;
else
oflag = O_WRONLY | O_CREAT | O_APPEND;
break;
default:
return (FILE*)EINVAL;
}
int fd = open(pathname, oflag);
if (fd == -1)
return NULL;
FILE *temp = malloc(sizeof(pathname) + sizeof(fd));
temp->filename = (char*)pathname;
temp->fd = fd;
return temp;
}
int fclose(FILE *stream) {
return close(stream->fd);
}
int fgetc(FILE *stream) {
char buf = '\0';
read(stream->fd, (void*)&buf, 1);
return (buf == '\0') ? (unsigned int)-1 : (unsigned int)buf;
}
int getchar(void) {
return fgetc(stdin);
}
char *fgets(char *restrict s, int n, FILE *restrict stream) {
s = malloc(n);
int i = 0;
char c = '\0';
while (i < n-1 && (c = fgetc(stream)) != -1 && (s[i++] = c) && c != '\n');
return (strlen(s) == 0) ? NULL : s;
}
int fputc(int c, FILE *stream) {
return (write(stream->fd, &c, 1) == -1 ) ? -1 : c;
}
int fputs(const char *restrict s, FILE *restrict stream) {
size_t i = 0;
while (i < strlen(s)) {
if (fputc(s[i], stream) == -1) return -1;
i++;
}
return 1; // FIXME
}
int rename(const char *old, const char *new) {
return sys_rename(old, new);
}
int putchar(int c) {
write(stdout->fd, &c, 1);
return (unsigned char)c;
}
int puts(const char *s) {
int i = 0;
while(s[i] != '\0') {
putchar(s[i]);
i++;
}
putchar('\n');
return 1; // FIXME
}
int vsnprintf(char *restrict s, size_t n, const char *restrict format, va_list ap) {
char *str;
int value;
size_t size = 0;
for (size_t i = 0; i < strlen(format) && size < n-1; i++) {
if (format[i] == '%') {
i++;
switch(format[i]) {
case 'c':
s[size] = (char) va_arg(ap, int);
size++;
break;
case 's':
str = va_arg(ap, char *);
for (size_t j = 0; j < strlen(str); j++) {
s[size] = str[j];
size++;
}
break;
case 'd':
value = va_arg(ap, int);
if (value == 0) {
s[size] = '0';
size++;
} if (value < 0) {
s[size] = '-';
value *= (-1);
size++;
}
long long power = 1;
while (value > power)
power *= 10;
if (power >= 10)
power /= 10;
while (value != 0) {
int digit = (int)(value / power);
s[size] = '0' + digit;
size++;
if (digit != 0)
value = value - digit * power;
if (power != 1)
power /= 10;
}
break;
}
} else {
s[size] = format[i];
size++;
}
}
s[size] = '\0';
return size;
}
int snprintf(char *restrict s, size_t n, const char *restrict format, ...) {
int size;
va_list ap;
va_start(ap, format);
size = vsnprintf(s, n, format, ap);
va_end(ap);
return size;
}
int vsprintf(char *restrict s, const char *restrict format, va_list ap) {
size_t n = strlen(s);
return vsnprintf(s, n, format, ap);
}
int sprintf(char *restrict s, const char *restrict format, ...) {
int size;
va_list ap;
va_start(ap, format);
size = vsprintf(s, format, ap);
va_end(ap);
return size;
}
int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap) {
char s[1024]; // FIXME
int size = vsprintf(s, format, ap);
fputs(s, stream);
return size;
}
int fprintf(FILE *restrict stream, const char *restrict format, ...) {
int size;
va_list ap;
va_start(ap, format);
size = vfprintf(stream, format, ap);
va_end(ap);
return size;
}
int vprintf(const char *restrict format, va_list ap) {
return vfprintf(stdout, format, ap);
}
int printf(const char *restrict format, ...) {
int size;
va_list ap;
va_start(ap, format);
size = vprintf(format, ap);
va_end(ap);
return size;
}