214 lines
4.2 KiB
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;
|
|
}
|
|
|