At least define a bunch of libc stuff

This commit is contained in:
K. Lange 2018-06-25 12:11:33 +09:00
parent 416ae2d1a3
commit a283332be6
16 changed files with 322 additions and 40 deletions

View File

@ -10,4 +10,6 @@ extern double fabs(double x);
extern double sin(double x);
extern double cos(double x);
double frexp(double x, int *exp);
#define HUGE_VAL (__builtin_huge_val())

View File

@ -22,6 +22,7 @@ extern int fclose(FILE * stream);
extern int fseek(FILE * stream, long offset, int whence);
extern long ftell(FILE * stream);
extern FILE * fdopen(int fd, const char *mode);
extern FILE * freopen(const char *path, const char *mode, FILE * stream);
extern size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream);
extern size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE * stream);
@ -50,7 +51,18 @@ extern int ungetc(int c, FILE * stream);
extern int feof(FILE * stream);
extern void clearerr(FILE * stream);
extern int ferror(FILE * stream);
extern char * strerror(int errnum);
extern int _fwouldblock(FILE * stream);
extern FILE * tmpfile(void);
extern int setvbuf(FILE * stream, char * buf, int mode, size_t size);
#define _IONBF 0
#define _IOLBF 1
#define _IOFBF 2
#define getc(s) fgetc(s)

View File

@ -19,6 +19,7 @@ extern int abs(int j);
extern int putenv(char * name);
extern int setenv(const char *name, const char *value, int overwrite);
extern double strtod(const char *nptr, char **endptr);
extern double atof(const char * nptr);
extern int atoi(const char * nptr);
extern long atol(const char * nptr);

View File

@ -26,6 +26,7 @@ extern char * strstr(const char * h, const char * n);
extern int strcmp(const char * l, const char * r);
extern int strncmp(const char *s1, const char *s2, size_t n);
extern int strcoll(const char * s1, const char * s2);
extern size_t strcspn(const char * s, const char * c);
extern size_t strspn(const char * s, const char * c);
@ -38,3 +39,5 @@ extern char * strcat(char *dest, const char *src);
extern char * strtok_r(char * str, const char * delim, char ** saveptr);
extern char * strncpy(char *dest, const char *src, size_t n);
extern char * strerror(int errnum);

View File

@ -19,3 +19,6 @@ extern struct tm *localtime(const time_t *timep);
extern size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
extern time_t time(time_t * out);
extern double difftime(time_t a, time_t b);
extern int clock(void);
#define CLOCKS_PER_SEC 1

View File

@ -54,6 +54,8 @@ extern int getopt(int argc, char * const argv[], const char * optstring);
extern char * optarg;
extern int optind, opterr, optopt;
extern int unlink(const char * pathname);
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2

View File

@ -38,7 +38,6 @@ DEFN_SYSCALL3(ioctl, 47, int, int, void *);
DEFN_SYSCALL2(access, 48, char *, int);
DEFN_SYSCALL2(stat, 49, char *, void *);
DEFN_SYSCALL1(umask, 51, int);
DEFN_SYSCALL1(unlink, 52, char *);
DEFN_SYSCALL3(waitpid, 53, int, int *, int);
DEFN_SYSCALL5(mount, SYS_MOUNT, char *, char *, char *, unsigned long, void *);
DEFN_SYSCALL2(lstat, SYS_LSTAT, char *, void *);

25
libc/math/frexp.c Normal file
View File

@ -0,0 +1,25 @@
#include <string.h>
#include <stdint.h>
double frexp(double x, int *exp) {
struct {
uint32_t lsw;
uint32_t msw;
} extract;
memcpy(&extract, &x, sizeof(double));
*exp = ((extract.msw & 0x7ff00000) >> 20) - 0x3FE;
struct {
uint32_t lsw;
uint32_t msw;
} out_double;
out_double.msw = (extract.msw & 0x800fffff) | 0x3FE00000;
out_double.lsw = extract.lsw;
double out;
memcpy(&out, &out_double, sizeof(double));
return out;
}

View File

@ -16,6 +16,7 @@ struct _FILE {
int read_from;
int ungetc;
int eof;
int bufsiz;
};
FILE _stdin = {
@ -26,6 +27,7 @@ FILE _stdin = {
.read_from = 0,
.ungetc = -1,
.eof = 0,
.bufsiz = BUFSIZ,
};
FILE _stdout = {
@ -36,6 +38,7 @@ FILE _stdout = {
.read_from = 0,
.ungetc = -1,
.eof = 0,
.bufsiz = BUFSIZ,
};
FILE _stderr = {
@ -46,6 +49,7 @@ FILE _stderr = {
.read_from = 0,
.ungetc = -1,
.eof = 0,
.bufsiz = BUFSIZ,
};
FILE * stdin = &_stdin;
@ -71,6 +75,18 @@ static char * stream_id(FILE * stream) {
extern char * _argv_0;
int setvbuf(FILE * stream, char * buf, int mode, size_t size) {
if (mode != _IOLBF) {
return -1; /* Unsupported */
}
if (buf) {
if (stream->read_buf) {
free(stream->read_buf);
}
stream->bufsiz = size;
}
return 0;
}
static size_t read_bytes(FILE * f, char * out, size_t len) {
size_t r_out = 0;
@ -89,10 +105,10 @@ static size_t read_bytes(FILE * f, char * out, size_t len) {
}
if (f->available == 0) {
if (f->offset == BUFSIZ) {
if (f->offset == f->bufsiz) {
f->offset = 0;
}
ssize_t r = read(fileno(f), &f->read_buf[f->offset], BUFSIZ - f->offset);
ssize_t r = read(fileno(f), &f->read_buf[f->offset], f->bufsiz - f->offset);
if (r < 0) {
//fprintf(stderr, "error condition\n");
return r_out;
@ -125,8 +141,7 @@ static size_t read_bytes(FILE * f, char * out, size_t len) {
return r_out;
}
FILE * fopen(const char *path, const char *mode) {
static void parse_mode(const char * mode, int * flags_, int * mask_) {
const char * x = mode;
int flags = 0;
@ -152,6 +167,15 @@ FILE * fopen(const char *path, const char *mode) {
++x;
}
*flags_ = flags;
*mask_ = mask;
}
FILE * fopen(const char *path, const char *mode) {
int flags, mask;
parse_mode(mode, &flags, &mask);
int fd = syscall_open(path, flags, mask);
if (fd < 0) {
@ -161,6 +185,7 @@ FILE * fopen(const char *path, const char *mode) {
FILE * out = malloc(sizeof(FILE));
out->fd = fd;
out->read_buf = malloc(BUFSIZ);
out->bufsiz = BUFSIZ;
out->available = 0;
out->read_from = 0;
out->offset = 0;
@ -170,6 +195,30 @@ FILE * fopen(const char *path, const char *mode) {
return out;
}
/* This is very wrong */
FILE * freopen(const char *path, const char *mode, FILE * stream) {
if (path) {
if (stream) {
fclose(stream);
}
int flags, mask;
parse_mode(mode, &flags, &mask);
int fd = syscall_open(path, flags, mask);
stream->fd = fd;
stream->available = 0;
stream->read_from = 0;
stream->offset = 0;
stream->ungetc = -1;
stream->eof = 0;
if (fd < 0) {
return NULL;
}
}
return stream;
}
int ungetc(int c, FILE * stream) {
if (stream->ungetc > 0)
return EOF;
@ -181,6 +230,7 @@ FILE * fdopen(int fd, const char *mode){
FILE * out = malloc(sizeof(FILE));
out->fd = fd;
out->read_buf = malloc(BUFSIZ);
out->bufsiz = BUFSIZ;
out->available = 0;
out->read_from = 0;
out->offset = 0;
@ -339,3 +389,7 @@ int feof(FILE * stream) {
void clearerr(FILE * stream) {
stream->eof = 0;
}
int ferror(FILE * stream) {
return 0; /* TODO */
}

15
libc/stdio/tmpfile.c Normal file
View File

@ -0,0 +1,15 @@
#include <stdio.h>
#include <unistd.h>
FILE * tmpfile(void) {
static int tmpfile_num = 1;
char tmp[100];
sprintf(tmp, "/tmp/tmp%d.%d", getpid(), tmpfile_num++);
FILE * out = fopen(tmp, "w+b");
unlink(tmp);
return out;
}

View File

@ -3,39 +3,5 @@
#include <stdlib.h>
double atof(const char * nptr) {
int sign = 1;
if (*nptr == '-') {
sign = -1;
nptr++;
}
long long decimal_part = 0;
while (*nptr && *nptr != '.') {
if (*nptr < '0' || *nptr > '9') {
return 0.0;
}
decimal_part *= 10LL;
decimal_part += (long long)(*nptr - '0');
nptr++;
}
double sub_part = 0;
double multiplier = 0.1;
if (*nptr == '.') {
nptr++;
while (*nptr) {
if (*nptr < '0' || *nptr > '9') {
return ((double)decimal_part) * (double)(sign);
}
sub_part += multiplier * (*nptr - '0');
multiplier *= 0.1;
nptr++;
}
}
return ((double)decimal_part + sub_part) * (double)(sign);
return strtod(nptr, NULL);
}

49
libc/stdlib/strtod.c Normal file
View File

@ -0,0 +1,49 @@
#include <stdlib.h>
double strtod(const char *nptr, char **endptr) {
int sign = 1;
if (*nptr == '-') {
sign = -1;
nptr++;
}
long long decimal_part = 0;
while (*nptr && *nptr != '.') {
if (*nptr < '0' || *nptr > '9') {
if (endptr) {
*endptr = (char *)nptr;
}
return 0.0;
}
decimal_part *= 10LL;
decimal_part += (long long)(*nptr - '0');
nptr++;
}
double sub_part = 0;
double multiplier = 0.1;
if (*nptr == '.') {
nptr++;
while (*nptr) {
if (*nptr < '0' || *nptr > '9') {
if (endptr) {
*endptr = (char *)nptr;
}
return ((double)decimal_part) * (double)(sign);
}
sub_part += multiplier * (*nptr - '0');
multiplier *= 0.1;
nptr++;
}
}
if (endptr) {
*endptr = (char *)nptr;
}
return ((double)decimal_part + sub_part) * (double)(sign);
}

View File

@ -51,6 +51,10 @@ int strcmp(const char * l, const char * r) {
return *(unsigned char *)l - *(unsigned char *)r;
}
int strcoll(const char * s1, const char * s2) {
return strcmp(s1,s2); /* TODO locales */
}
size_t strlen(const char * s) {
const char * a = s;
const size_t * w;

126
libc/string/strerror.c Normal file
View File

@ -0,0 +1,126 @@
#include <string.h>
#include <errno.h>
static char * _error_strings[256] = {
[EPERM] = "Not super-user",
[ENOENT] = "No such file or directory",
[ESRCH] = "No such process",
[EINTR] = "Interrupted system call",
[EIO] = "I/O error",
[ENXIO] = "No such device or address",
[E2BIG] = "Arg list too long",
[ENOEXEC] = "Exec format error",
[EBADF] = "Bad file number",
[ECHILD] = "No children",
[EAGAIN] = "No more processes",
[ENOMEM] = "Not enough core",
[EACCES] = "Permission denied",
[EFAULT] = "Bad address",
[ENOTBLK] = "Block device required",
[EBUSY] = "Mount device busy",
[EEXIST] = "File exists",
[EXDEV] = "Cross-device link",
[ENODEV] = "No such device",
[ENOTDIR] = "Not a directory",
[EISDIR] = "Is a directory",
[EINVAL] = "Invalid argument",
[ENFILE] = "Too many open files in system",
[EMFILE] = "Too many open files",
[ENOTTY] = "Not a typewriter",
[ETXTBSY] = "Text file busy",
[EFBIG] = "File too large",
[ENOSPC] = "No space left on device",
[ESPIPE] = "Illegal seek",
[EROFS] = "Read only file system",
[EMLINK] = "Too many links",
[EPIPE] = "Broken pipe",
[EDOM] = "Math arg out of domain of func",
[ERANGE] = "Math result not representable",
[ENOMSG] = "No message of desired type",
[EIDRM] = "Identifier removed",
[ECHRNG] = "Channel number out of range",
[EL2NSYNC] = "Level 2 not synchronized",
[EL3HLT] = "Level 3 halted",
[EL3RST] = "Level 3 reset",
[ELNRNG] = "Link number out of range",
[EUNATCH] = "Protocol driver not attached",
[ENOCSI] = "No CSI structure available",
[EL2HLT] = "Level 2 halted",
[EDEADLK] = "Deadlock condition",
[ENOLCK] = "No record locks available",
[EBADE] = "Invalid exchange",
[EBADR] = "Invalid request descriptor",
[EXFULL] = "Exchange full",
[ENOANO] = "No anode",
[EBADRQC] = "Invalid request code",
[EBADSLT] = "Invalid slot",
[EDEADLOCK] = "File locking deadlock error",
[EBFONT] = "Bad font file fmt",
[ENOSTR] = "Device not a stream",
[ENODATA] = "No data (for no delay io)",
[ETIME] = "Timer expired",
[ENOSR] = "Out of streams resources",
[ENONET] = "Machine is not on the network",
[ENOPKG] = "Package not installed",
[EREMOTE] = "The object is remote",
[ENOLINK] = "The link has been severed",
[EADV] = "Advertise error",
[ESRMNT] = "Srmount error",
[ECOMM] = "Communication error on send",
[EPROTO] = "Protocol error",
[EMULTIHOP] = "Multihop attempted",
[ELBIN] = "Inode is remote (not really error)",
[EDOTDOT] = "Cross mount point (not really error)",
[EBADMSG] = "Trying to read unreadable message",
[EFTYPE] = "Inappropriate file type or format",
[ENOTUNIQ] = "Given log. name not unique",
[EBADFD] = "f.d. invalid for this operation",
[EREMCHG] = "Remote address changed",
[ELIBACC] = "Can't access a needed shared lib",
[ELIBBAD] = "Accessing a corrupted shared lib",
[ELIBSCN] = ".lib section in a.out corrupted",
[ELIBMAX] = "Attempting to link in too many libs",
[ELIBEXEC] = "Attempting to exec a shared library",
[ENOSYS] = "Function not implemented",
[ENOTEMPTY] = "Directory not empty",
[ENAMETOOLONG] = "File or path name too long",
[ELOOP] = "Too many symbolic links",
[EOPNOTSUPP] = "Operation not supported on transport endpoint",
[EPFNOSUPPORT] = "Protocol family not supported",
[ECONNRESET] = "Connection reset by peer",
[ENOBUFS] = "No buffer space available",
[EAFNOSUPPORT] = "Address family not supported by protocol family",
[EPROTOTYPE] = "Protocol wrong type for socket",
[ENOTSOCK] = "Socket operation on non-socket",
[ENOPROTOOPT] = "Protocol not available",
[ESHUTDOWN] = "Can't send after socket shutdown",
[ECONNREFUSED] = "Connection refused",
[EADDRINUSE] = "Address already in use",
[ECONNABORTED] = "Connection aborted",
[ENETUNREACH] = "Network is unreachable",
[ENETDOWN] = "Network interface is not configured",
[ETIMEDOUT] = "Connection timed out",
[EHOSTDOWN] = "Host is down",
[EHOSTUNREACH] = "Host is unreachable",
[EINPROGRESS] = "Connection already in progress",
[EALREADY] = "Socket already connected",
[EDESTADDRREQ] = "Destination address required",
[EMSGSIZE] = "Message too long",
[EPROTONOSUPPORT] = "Unknown protocol",
[ESOCKTNOSUPPORT] = "Socket type not supported",
[EADDRNOTAVAIL] = "Address not available",
[EISCONN] = "Socket is already connected",
[ENOTCONN] = "Socket is not connected",
[ENOTSUP] = "Not supported",
[EOVERFLOW] = "Value too large for defined data type",
[ECANCELED] = "Operation canceled",
[ENOTRECOVERABLE] = "State not recoverable",
[EOWNERDEAD] = "Previous owner died",
[ESTRPIPE] = "Streams pipe error",
};
char * strerror(int errnum) {
if (errnum > 255) return "???";
if (!_error_strings[errnum]) return "???";
return _error_strings[errnum];
}

5
libc/time/clock.c Normal file
View File

@ -0,0 +1,5 @@
#include <time.h>
int clock(void) {
return -1;
}

16
libc/unistd/unlink.c Normal file
View File

@ -0,0 +1,16 @@
#include <unistd.h>
#include <errno.h>
#include <syscall.h>
#include <syscall_nums.h>
DEFN_SYSCALL1(unlink, SYS_UNLINK, char *);
int unlink(const char * pathname) {
int result = syscall_unlink((char *)pathname);
if (result < 0) {
errno = -result;
return -1;
}
return 0;
}