summaryrefslogtreecommitdiff
path: root/src/user/lib/libc
diff options
context:
space:
mode:
authorAlex AUVOLAT <alexis211@gmail.com>2013-06-08 23:09:52 +0200
committerAlex AUVOLAT <alexis211@gmail.com>2013-06-08 23:09:52 +0200
commit4d65fcb9a8b6c7c6fd5a3390c46a96d11b6a80d4 (patch)
treec193acf64ff2db985f6664f161cf586c3caeb684 /src/user/lib/libc
parenteae9997d3c2dbaef53022ddabe61c1800a619499 (diff)
downloadTCE-4d65fcb9a8b6c7c6fd5a3390c46a96d11b6a80d4.tar.gz
TCE-4d65fcb9a8b6c7c6fd5a3390c46a96d11b6a80d4.zip
All FWIK is deleted. YOSH is now pure C. Not-working KBASIC included.
Diffstat (limited to 'src/user/lib/libc')
-rw-r--r--src/user/lib/libc/Makefile3
-rw-r--r--src/user/lib/libc/include/ctype.h24
-rw-r--r--src/user/lib/libc/include/readline.h4
-rw-r--r--src/user/lib/libc/include/setjmp.h25
-rw-r--r--src/user/lib/libc/include/stdio.h53
-rw-r--r--src/user/lib/libc/include/stdlib.h15
-rw-r--r--src/user/lib/libc/include/string.h5
-rw-r--r--src/user/lib/libc/include/tce/syscall.h16
-rw-r--r--src/user/lib/libc/start.c18
-rw-r--r--src/user/lib/libc/std/ctype.c28
-rw-r--r--src/user/lib/libc/std/readline.c19
-rw-r--r--src/user/lib/libc/std/setjmp.asm37
-rw-r--r--src/user/lib/libc/std/stdio.c245
-rw-r--r--src/user/lib/libc/std/stdlib.c32
-rw-r--r--src/user/lib/libc/std/string.c113
-rw-r--r--src/user/lib/libc/tce/syscall.c28
16 files changed, 602 insertions, 63 deletions
diff --git a/src/user/lib/libc/Makefile b/src/user/lib/libc/Makefile
index 14a5421..d706635 100644
--- a/src/user/lib/libc/Makefile
+++ b/src/user/lib/libc/Makefile
@@ -1,6 +1,7 @@
Out = _libc.o
Obj = tce/syscall.o std/_dlmalloc.o \
- std/stdio.o std/stdlib.o std/string.o std/sched.o std/readline.o \
+ std/stdio.o std/stdlib.o std/string.o std/ctype.o std/setjmp.o \
+ std/sched.o std/readline.o \
start.o
include $(SrcPath)/common.make
diff --git a/src/user/lib/libc/include/ctype.h b/src/user/lib/libc/include/ctype.h
new file mode 100644
index 0000000..10a64df
--- /dev/null
+++ b/src/user/lib/libc/include/ctype.h
@@ -0,0 +1,24 @@
+#ifndef DEF_LIBC_CTYPE_H
+#define DEF_LIBC_CTYPE_H
+
+#include <types.h>
+
+#ifdef __cplusplus
+extern "C" { namespace libc {
+#endif
+
+
+int isalpha(int c);
+int isdigit(int c);
+int isalnum(int c);
+
+int tolower(int c);
+int toupper(int c);
+
+
+#ifdef __cplusplus
+} }
+#endif
+
+#endif
+
diff --git a/src/user/lib/libc/include/readline.h b/src/user/lib/libc/include/readline.h
index 1ec5baa..9fa2ee7 100644
--- a/src/user/lib/libc/include/readline.h
+++ b/src/user/lib/libc/include/readline.h
@@ -14,8 +14,8 @@ typedef struct _rdln_hist {
extern "C" { namespace libc {
#endif
char *readln();
-char* freadln(FILE f); // minimal line-reading function. user must free the returned value.
-char* freadline(FILE f, readline_history *h);
+char* freadln(FILE *f); // minimal line-reading function. user must free the returned value.
+char* freadline(FILE *f, readline_history *h);
#ifdef __cplusplus
} }
#endif
diff --git a/src/user/lib/libc/include/setjmp.h b/src/user/lib/libc/include/setjmp.h
new file mode 100644
index 0000000..3bf2027
--- /dev/null
+++ b/src/user/lib/libc/include/setjmp.h
@@ -0,0 +1,25 @@
+#ifndef DEF_LIBC_SETJMP_H
+#define DEF_LIBC_SETJMP_H
+
+#include <types.h>
+
+typedef struct {
+ uint32_t ebp; //0
+ uint32_t ebx; //4
+ uint32_t edi; //8
+ uint32_t esi; //12
+ uint32_t esp; //16
+ uint32_t eip; //20
+} jmp_buf[1];
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int setjmp(jmp_buf env);
+void longjmp(jmp_buf, int val);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/user/lib/libc/include/stdio.h b/src/user/lib/libc/include/stdio.h
index 72d355a..8fbefcd 100644
--- a/src/user/lib/libc/include/stdio.h
+++ b/src/user/lib/libc/include/stdio.h
@@ -8,14 +8,57 @@
extern "C" { namespace libc {
#endif
+#define EOF 0x1E0F
+
+#define TERM_INPUT_BUFFER_SIZE 256
+
+typedef struct {
+ int fd;
+ long pos; // -1 : it's a stream
+ file_info info;
+ // terminal input buffer
+ // Possible states :
+ // - tib_u_begin = tib_u_end = tib_begin : buffer is empty
+ // - tib_begin = tib_u_begin < tib_u_end : buffer contains some data
+ // - tib_begin < tib_u_begin < tib_u_end : buffer contains some data that is
+ // being read, and some space for putting back characters
+ char *tib_begin, *tib_end, *tib_u_begin, *tib_u_end;
+ int term_echo; // enable echoing of entered keypresses ?
+
+} FILE;
+
extern FILE term;
+#define stdin (&term)
+#define stdout (&term)
+
+
+#define SEEK_SET 0x5EEC0001
+#define SEEK_CUR 0x5EEC0002
+#define SEEK_END 0x5EEC0003
+FILE *fopen(const char *path, const char *mode);
+void __tce_libc_fsetup(FILE *f); // INTERNAL
+
+// These two handle buffering for terminals
+int fgetc(FILE*);
+int ungetc(int, FILE*);
+
+// These do not handle buffering for terminals
+size_t fread(void* ptr, size_t size, size_t nmemb, FILE*);
+size_t fwrite(void* ptr, size_t size, size_t nmemb, FILE*);
+size_t fseek(FILE *stream, long offset, int whence);
+long ftell(FILE *stream);
+void fclose(FILE *f);
+
+int getchar();
+int scanf(const char *s, ...);
+
+int print(const char *s);
+int printf(const char *s, ...);
-void print(const char *s);
-void printf(const char *s, ...);
-void fprint(FILE f, const char *s);
-void fprintf(FILE f, const char *s, ...);
-void vfprintf(FILE f, const char *s, va_list arg);
+int fprint(FILE *f, const char *s);
+int fprintf(FILE *f, const char *s, ...);
+int vfprintf(FILE *f, const char *s, va_list arg);
#ifdef __cplusplus
} }
diff --git a/src/user/lib/libc/include/stdlib.h b/src/user/lib/libc/include/stdlib.h
index 1cc5d16..e1b3326 100644
--- a/src/user/lib/libc/include/stdlib.h
+++ b/src/user/lib/libc/include/stdlib.h
@@ -1,5 +1,5 @@
-#ifndef DEF_STDLIB_H
-#define DEF_STDLIB_H
+#ifndef DEF_LIBC_STDLIB_H
+#define DEF_LIBC_STDLIB_H
#include <types.h>
#include <tce/syscall.h>
@@ -8,8 +8,19 @@
extern "C" { namespace libc {
#endif
+int atoi(char*);
+double atof(char*);
+
+#define RAND_MAX 32767
+int rand();
+void srand(unsigned int);
+
+void exit(int);
void abort();
extern volatile int errno;
+
+
+
#ifdef __cplusplus
} }
#endif
diff --git a/src/user/lib/libc/include/string.h b/src/user/lib/libc/include/string.h
index 5b86868..2f4f4ca 100644
--- a/src/user/lib/libc/include/string.h
+++ b/src/user/lib/libc/include/string.h
@@ -18,6 +18,7 @@ char *strdup(const char *src);
char *strchr(const char *str, int c);
char *strcat(char *dest, const char *src);
int strcmp(const char *s1, const char *s2);
+char *strncpy(char *dest, const char *src, int max);
char* format_int(char* buf, int number);
char* format_hex(char *buf, unsigned v);
@@ -25,6 +26,10 @@ int printf_str_len(const char *fmt, va_list arg);
int vsprintf(char *buf, const char *fmt, va_list arg);
int sprintf(char *buf, const char *fmt, ...);
+
+void simplify_path(char *p); // simplifies /../, // and /./
+char *path_cat(const char *a, const char *b, int trailing_slash); // allocates a new buffer
+
#ifdef __cplusplus
} }
#endif
diff --git a/src/user/lib/libc/include/tce/syscall.h b/src/user/lib/libc/include/tce/syscall.h
index 6679f1a..4a1c6ef 100644
--- a/src/user/lib/libc/include/tce/syscall.h
+++ b/src/user/lib/libc/include/tce/syscall.h
@@ -23,17 +23,17 @@ int proc_priv();
void* sbrk(ptrdiff_t size);
void brk(void* ptr);
-int run(const char* file, const char** args, FILE zero_fd);
+int run(const char* file, const char** args, int zero_fd);
int waitpid(int pid, int block);
-FILE open(const char* filename, int mode);
-FILE open_relative(FILE root, const char* filename, int mode);
+int open(const char* filename, int mode);
+int open_relative(int root, const char* filename, int mode);
int stat(const char* filename, file_info *info);
-int stat_relative(FILE root, const char* filename, file_info *info);
-int statf(FILE file, file_info *info);
-void close(FILE file);
-int read(FILE file, size_t offset, size_t len, char *buffer);
-int write(FILE file, size_t offset, size_t len, const char *buffer);
+int stat_relative(int root, const char* filename, file_info *info);
+int statf(int file, file_info *info);
+void close(int file);
+int read(int file, size_t offset, size_t len, char *buffer);
+int write(int file, size_t offset, size_t len, const char *buffer);
int link(const char* from, const char* to, int mode);
#ifdef __cplusplus
diff --git a/src/user/lib/libc/start.c b/src/user/lib/libc/start.c
index f15f90d..3f51fdb 100644
--- a/src/user/lib/libc/start.c
+++ b/src/user/lib/libc/start.c
@@ -1,18 +1,28 @@
#include <tce/syscall.h>
-extern int main(char **args);
+#include <stdio.h>
+
+extern int main(int argc, char **argv);
extern size_t start_ctors, end_ctors, start_dtors, end_dtors;
-void start(char **args) {
- size_t *call;
+void __tce_libc_start(char **args) {
+ // setup stdio
+ term.fd = 0;
+ __tce_libc_fsetup(&term);
+ // call C++ static constructors
+ size_t *call;
for (call = &start_ctors; call < &end_ctors; call++) {
((void(*)(void))*call)();
}
- int ret = main(args);
+ // call main
+ char **lastarg = args;
+ while (*lastarg) lastarg++;
+ int ret = main((lastarg - args), args);
+ // call C++ static destructors
for (call = &start_dtors; call < &end_dtors; call++) {
((void(*)(void))*call)();
}
diff --git a/src/user/lib/libc/std/ctype.c b/src/user/lib/libc/std/ctype.c
new file mode 100644
index 0000000..f0e7750
--- /dev/null
+++ b/src/user/lib/libc/std/ctype.c
@@ -0,0 +1,28 @@
+#include <ctype.h>
+
+
+int isalpha(int c) {
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+}
+
+int isdigit(int c) {
+ return (c >= '0' && c <= '9');
+}
+
+int isalnum(int c) {
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9');
+}
+
+int tolower(int c) {
+ if (c >= 'A' && c <= 'Z') {
+ return c + ('a' - 'A');
+ }
+ return c;
+}
+
+int toupper(int c) {
+ if (c >= 'a' && c <= 'z') {
+ return c - ('a' - 'A');
+ }
+ return c;
+}
diff --git a/src/user/lib/libc/std/readline.c b/src/user/lib/libc/std/readline.c
index 50e4f0d..4177bf6 100644
--- a/src/user/lib/libc/std/readline.c
+++ b/src/user/lib/libc/std/readline.c
@@ -1,15 +1,14 @@
#include <readline.h>
#include <stdlib.h>
-char* freadln(FILE f) {
- fprint(f, "\x1b[e"); // enable keyboard echo
+char* freadln(FILE *f) {
int i;
char *p = (char*)malloc(256);
char *b = p;
while (1) {
- int l = read(f, 0, 255, b);
+ int l = fread(b, 255, 1, f);
if (l < 0) {
free(b);
return 0;
@@ -36,15 +35,14 @@ char* freadln(FILE f) {
}
char* readln() {
- return freadln(term);
+ return freadln(&term);
}
// ** READLINE
-char *freadline(FILE f, readline_history *h) {
+char *freadline(FILE *f, readline_history *h) {
int i;
- fprint(f, "\x1b[h"); // disable keyboard echo
if (h->str == 0) {
h->str = (char**)malloc(h->max * sizeof(char*));
@@ -78,12 +76,15 @@ char *freadline(FILE f, readline_history *h) {
int te = cur - str;
char buf[16];
- int l = read(f, 0, 16, buf);
+ int l = fread(buf, 16, 1, f);
if (l < 0) return 0;
char *in = buf;
while (in < buf + l) {
- if (*in == 27) {
+ if (*in == 4) { // eot
+ fprintf(f, "^D\n");
+ return 0;
+ } else if (*in == 27) {
in++;
if (*in == '[') {
in++;
@@ -142,7 +143,7 @@ char *freadline(FILE f, readline_history *h) {
if (finished) {
- fprintf(f, "\n");
+ fprint(f, "\n");
if (h->str[h->n-1] != str) h->n--;
diff --git a/src/user/lib/libc/std/setjmp.asm b/src/user/lib/libc/std/setjmp.asm
new file mode 100644
index 0000000..399ad0c
--- /dev/null
+++ b/src/user/lib/libc/std/setjmp.asm
@@ -0,0 +1,37 @@
+[GLOBAL setjmp]
+setjmp:
+ mov edx, [esp + 4] ; read jmp_buf pointer into edx
+ mov eax, [esp] ; read return address into eax
+
+ mov [edx], ebp
+ mov [edx+4], ebx
+ mov [edx+8], edi
+ mov [edx+12], esi
+ mov [edx+16], esp
+ mov [edx+20], eax
+
+ xor eax, eax ; return 0
+ ret
+
+[GLOBAL longjmp]
+longjmp:
+ mov edx, [esp + 4] ; read jmp_buf pointer into edx
+ mov eax, [esp + 8] ; move return value into eax
+
+ ; make sure eax is not 0
+ cmp eax, 0
+ jne next
+ inc eax ; eax is 0, set it to 1
+
+next:
+ mov esp, [edx + 16] ; read esp
+ mov ebx, [edx + 20] ; read return address
+ mov [esp], ebx ; update return address
+
+ mov ebp, [edx]
+ mov ebx, [edx + 4]
+ mov edi, [edx + 8]
+ mov esi, [edx + 12]
+
+ ret
+
diff --git a/src/user/lib/libc/std/stdio.c b/src/user/lib/libc/std/stdio.c
index 12064be..be65505 100644
--- a/src/user/lib/libc/std/stdio.c
+++ b/src/user/lib/libc/std/stdio.c
@@ -1,37 +1,258 @@
+#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <tce/syscall.h>
-#include <readline.h>
+#include <ctype.h>
-FILE term = 0;
-void print(const char *s) {
- fprint(term, s);
+FILE term;
+
+
+// GENERAL FILE ROUTINES
+
+FILE *fopen(const char *path, const char *mode) {
+ int m = 0;
+ if (strchr(mode, 'r')) m |= FM_READ;
+ if (strchr(mode, 'w')) m |= FM_WRITE;
+ if (strchr(mode, 't')) m |= FM_TRUNC;
+ if (strchr(mode, 'c')) m |= FM_CREATE;
+
+ FILE *ret = malloc(sizeof(FILE));
+ if (!ret) return NULL;
+
+ ret->fd = open(path, m);
+ if (ret->fd < 0) {
+ errno = ret->fd;
+ free(ret);
+ return NULL;
+ }
+ __tce_libc_fsetup(ret);
+
+ return ret;
+}
+
+void __tce_libc_fsetup(FILE *f) {
+ statf(f->fd, &f->info);
+ f->pos = 0;
+
+ if (f->info.type & FT_TERMINAL) {
+ f->pos = -1;
+
+ f->tib_begin = malloc(TERM_INPUT_BUFFER_SIZE);
+ f->tib_end = f->tib_begin + TERM_INPUT_BUFFER_SIZE;
+ f->tib_u_begin = f->tib_begin;
+ f->tib_u_end = f->tib_u_begin;
+ f->term_echo = 1;
+ }
+}
+
+int fgetc(FILE *f) {
+ if ((f->info.type & FT_TERMINAL) && f->tib_begin) {
+ if (f->tib_u_end == f->tib_u_begin) {
+ f->tib_u_begin = f->tib_u_end = f->tib_begin;
+ // read one line into buffer
+ int cont = 1;
+ while (cont) {
+ int k;
+ int n = read(f->fd, 0, f->tib_end - f->tib_u_end, f->tib_u_end);
+ for (k = 0; k < n; k++) {
+ if (f->term_echo) fprintf(f, "%c", f->tib_u_end[k]);
+ if (f->tib_u_end[k] == '\n' || f->tib_u_end[k] == 4) cont = 0;
+ }
+ f->tib_u_end += k;
+ if (f->tib_u_end == f->tib_end) cont = 0;
+ }
+
+ }
+
+ if (f->tib_u_end > f->tib_u_begin) {
+ char c = *f->tib_u_begin;
+ f->tib_u_begin++;
+ if (f->tib_u_begin == f->tib_end) {
+ f->tib_u_begin = f->tib_u_end = f->tib_begin; // empty buffer
+ }
+ return c;
+ }
+ } else {
+ char c;
+ int r = read(f->fd, (f->pos == -1 ? 0 : f->pos), 1, &c);
+ if (r == 1) {
+ if (f->pos != -1) f->pos++;
+ return c;
+ }
+ }
+ return EOF;
+}
+
+int ungetc(int c, FILE *f) {
+ if (f->info.type & FT_TERMINAL && f->tib_begin) {
+ if (f->tib_u_begin > f->tib_begin) {
+ // buffer contains data which is partially read already
+ f->tib_u_begin--;
+ *(f->tib_u_begin) = c;
+ } else if (f->tib_u_end == f->tib_u_begin) {
+ // buffer is totally empty
+ *(f->tib_u_end) = c;
+ f->tib_u_end++;
+ } else {
+ return EOF; // no space in buffer.
+ }
+ } else if (f->pos >0) {
+ f->pos--;
+ } else {
+ return EOF;
+ }
+ return c;
+}
+
+size_t fread(void *ptr, size_t size, size_t nmemb, FILE* f) {
+ if (size * nmemb == 0) return 0;
+
+ int r = read(f->fd, (f->pos == -1 ? 0 : f->pos), size * nmemb, ptr);
+ if (r > 0) {
+ if (f->pos != -1) f->pos += r;
+ return r;
+ } else {
+ errno = r;
+ return 0;
+ }
+}
+
+size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *f) {
+ if (size * nmemb == 0) return 0;
+ int r = write(f->fd, (f->pos == -1 ? 0 : f->pos), size * nmemb, ptr);
+ if (r > 0) {
+ if (f->pos != -1) f->pos += r;
+ return r;
+ } else {
+ errno = r;
+ return 0;
+ }
+}
+
+size_t fseek(FILE *f, long offset, int whence) {
+ // Update info
+ statf(f->fd, &f->info);
+
+ if (!(f->info.type & FT_FILE)) {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (whence == SEEK_CUR) {
+ offset += f->pos;
+ }
+ if (whence == SEEK_END) {
+ offset = f->info.size - offset;
+ }
+
+ if (offset > f->info.size || offset < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ f->pos = offset;
+
+ return 0;
+}
+
+long ftell(FILE *f) {
+ return f->pos;
+}
+
+void fclose(FILE *f) {
+ if (f->tib_begin) free(f->tib_begin);
+ close(f->fd);
+ free(f);
+}
+
+// COMFY INPUT FUNCTIONS
+
+int getchar() {
+ return fgetc(&term);
+}
+
+int scanf(const char *format, ...) {
+ // rudimentary implementation
+ int r = 0;
+
+ va_list ap;
+ va_start(ap, format);
+
+ while (*format) {
+ if (*format == '%') {
+ format++;
+ if (!(*format)) break;
+
+ if (*format == 'd' || *format == 'i') {
+ int c = fgetc(&term);
+
+ int *ret = va_arg(ap, int*);
+ *ret = 0;
+
+ while (isdigit(c)) {
+ (*ret) *= 10;
+ (*ret) += (c - '0');
+ r++;
+ c = fgetc(&term);
+ }
+ ungetc(c, &term);
+ } else if (*format == 'c') {
+ char *c = va_arg(ap, char*);
+ *c = fgetc(&term);
+ r++;
+ }
+ format++;
+ } else {
+ int c = fgetc(&term);
+ if (c == *format) {
+ r++;
+ format++;
+ } else {
+ ungetc(c, &term);
+ break;
+ }
+ }
+ }
+
+ va_end(ap);
+ return r;
+}
+
+// COMFY OUTPUT FUNCTIONS
+
+int print(const char *s) {
+ fprint(&term, s);
+ return strlen(s);
}
-void printf(const char *format, ...) {
+int printf(const char *format, ...) {
va_list ap;
+ int l;
va_start(ap, format);
- vfprintf(term, format, ap);
+ l = vfprintf(&term, format, ap);
va_end(ap);
+ return l;
}
-void fprint(FILE f, const char *s) {
- write(f, 0, strlen(s), s);
+int fprint(FILE *f, const char *s) {
+ return fwrite((void*)s, strlen(s), 1, f);
}
-void fprintf(FILE f, const char* format, ...) {
+int fprintf(FILE *f, const char* format, ...) {
va_list ap;
+ int l;
va_start(ap, format);
- vfprintf(f, format, ap);
+ l = vfprintf(f, format, ap);
va_end(ap);
+ return l;
}
-void vfprintf(FILE f, const char *fmt, va_list ap) {
+int vfprintf(FILE *f, const char *fmt, va_list ap) {
va_list ap2;
va_copy(ap2, ap);
int l = printf_str_len(fmt, ap2);
va_end(ap2);
char buf[l+1];
l = vsprintf(buf, fmt, ap);
- if (l > 0) write(f, 0, l, buf);
+ if (l > 0) return fwrite(buf, l, 1, f);
+ return 0;
}
diff --git a/src/user/lib/libc/std/stdlib.c b/src/user/lib/libc/std/stdlib.c
index 9d46b5c..15f9ddc 100644
--- a/src/user/lib/libc/std/stdlib.c
+++ b/src/user/lib/libc/std/stdlib.c
@@ -1,8 +1,38 @@
#include <stdlib.h>
#include <stdio.h>
+#include <ctype.h>
volatile int errno;
+void exit(int k) {
+ process_exit(k);
+}
+
void abort() {
- process_exit(100 + errno);
+ process_exit(300 + errno);
+}
+
+
+// Random generator
+
+static unsigned int rnd;
+
+void srand(unsigned int l) {
+ rnd = l;
+}
+
+int rand() {
+ rnd = rnd * 1103515245 + 12345;
+ return (unsigned int)(rnd / 65536) % (RAND_MAX + 1);
+}
+
+// ASCII to int
+
+int atoi(char *s) {
+ int r = 0;
+ while (*s >= '0' && *s <= '9') {
+ r *= 10;
+ r += (*s) - '0';
+ };
+ return r;
}
diff --git a/src/user/lib/libc/std/string.c b/src/user/lib/libc/std/string.c
index 619b8c6..02225a6 100644
--- a/src/user/lib/libc/std/string.c
+++ b/src/user/lib/libc/std/string.c
@@ -17,7 +17,18 @@ char *strchr(const char *str, int c) {
char *strcpy(char *dest, const char *src) {
memcpy(dest, src, strlen(src) + 1);
- return (char*)src;
+ return (char*)dest;
+}
+
+char *strncpy(char *dest, const char *src, int n) {
+ size_t i;
+
+ for (i = 0; i < n && src[i] != '\0'; i++)
+ dest[i] = src[i];
+ for ( ; i < n; i++)
+ dest[i] = '\0';
+
+ return dest;
}
char *strdup(const char *src) {
@@ -29,11 +40,10 @@ char *strdup(const char *src) {
char *strcat(char *dest, const char *src) {
char *dest2 = dest;
- dest2 += strlen(dest) - 1;
+ while (*dest2) dest2++; // move to end of string
+
while (*src) {
- *dest2 = *src;
- src++;
- dest2++;
+ *(dest2++) = *(src++);
}
*dest2 = 0;
return dest;
@@ -133,6 +143,8 @@ int printf_str_len(const char *format, va_list ap) {
va_arg(ap, void*);
} else if (*format == 's') {
l += strlen(va_arg(ap, const char*));
+ } else if (*format == 'c') {
+ l += 1;
}
} else {
l++;
@@ -164,6 +176,10 @@ int vsprintf(char *buf, const char *format, va_list ap) {
const char *s = va_arg(ap, const char*);
strcpy(end, s);
end += strlen(s);
+ } else if (*format == 'c') {
+ char k = va_arg(ap, int);
+ *(end++) = k;
+ *end = 0;
}
format++;
} else {
@@ -173,3 +189,90 @@ int vsprintf(char *buf, const char *format, va_list ap) {
*end = 0;
return end - buf;
}
+
+
+// ****** PATH CONCATENATION FUNCTION *******
+
+
+void simplify_path(char* p) {
+ char *it = p;
+ char *member = it;
+ while (*it != 0) {
+ if (*it == '/') {
+ if (it == member && it != p) {
+ // two consecutive slashes
+ char *i = member;
+ while (1) {
+ i[0] = i[1];
+ if (i[0] == 0) break;
+ i++;
+ }
+ } else {
+ *it = 0;
+ if (strcmp(member, ".") == 0) {
+ char *i = member;
+ while (1) {
+ i[0] = i[2];
+ if (i[0] == 0) break;
+ i++;
+ }
+ } else if (strcmp(member, "..") == 0) {
+ *it = '/';
+ char* start = member - 2;
+ char* next = member + 3;
+ while (start > p && *start != '/') {
+ start--;
+ }
+ start++;
+ it = member = start;
+ while (1) {
+ *start = *next;
+ if (*start == 0) break;
+ start++;
+ next++;
+ }
+ } else {
+ *it = '/';
+ it++;
+ member = it;
+ }
+ }
+ } else {
+ it++;
+ }
+ }
+}
+
+char* path_cat(const char *a, const char *b, int trailing_slash) {
+ int len, la = strlen(a), lb = strlen(b);
+ if (b[0] == '/') {
+ len = lb + 2;
+ } else {
+ len = la + lb + 3;
+ }
+ char *buf = malloc(len + 1);
+ if (b[0] == '/') {
+ memcpy(buf, b, lb);
+ if (buf[lb-1] != '/') {
+ buf[lb++] = '/';
+ }
+ buf[lb] = 0;
+ } else {
+ memcpy(buf, a, la);
+ if (buf[la-1] != '/') {
+ buf[la++] = '/';
+ }
+ memcpy(buf + la, b, lb);
+ if (buf[la + lb - 1] != '/') {
+ buf[la + lb] = '/';
+ lb++;
+ }
+ buf[la + lb] = 0;
+ }
+ simplify_path(buf);
+ if (!trailing_slash) {
+ int l = strlen(buf);
+ if (buf[l-1] == '/') buf[l-1] = 0;
+ }
+ return buf;
+}
diff --git a/src/user/lib/libc/tce/syscall.c b/src/user/lib/libc/tce/syscall.c
index acdcc51..f4f1333 100644
--- a/src/user/lib/libc/tce/syscall.c
+++ b/src/user/lib/libc/tce/syscall.c
@@ -75,7 +75,7 @@ void brk(void* ptr) {
// ********** proc
-int run(const char* filename, const char** args, FILE zero_fd) {
+int run(const char* filename, const char** args, int zero_fd) {
return call(SC_RUN, (unsigned)filename, (unsigned)args, (unsigned)zero_fd, 0, 0);
}
@@ -85,36 +85,36 @@ int waitpid(int p, int block) {
// ********** file
-FILE open(const char* filename, int mode) {
+int open(const char* filename, int mode) {
return call(SC_OPEN, (unsigned)filename, mode, 0, 0, 0);
}
-FILE open_relative(FILE root, const char* filename, int mode) {
- return call(SC_OPEN_RELATIVE, root, (unsigned) filename, mode, 0, 0);
+int open_relative(int root_fd, const char* filename, int mode) {
+ return call(SC_OPEN_RELATIVE, root_fd, (unsigned) filename, mode, 0, 0);
}
int stat(const char* filename, file_info *info) {
return call(SC_STAT, (unsigned) filename, (unsigned) info, 0, 0, 0);
}
-int stat_relative(FILE root, const char* filename, file_info *info) {
- return call(SC_STAT_RELATIVE, root, (unsigned) filename, (unsigned) info, 0, 0);
+int stat_relative(int root_fd, const char* filename, file_info *info) {
+ return call(SC_STAT_RELATIVE, root_fd, (unsigned) filename, (unsigned) info, 0, 0);
}
-int statf(FILE file, file_info *info) {
- return call(SC_STATF, file, (unsigned)info, 0, 0, 0);
+int statf(int file_fd, file_info *info) {
+ return call(SC_STATF, file_fd, (unsigned)info, 0, 0, 0);
}
-void close(FILE file) {
- call(SC_CLOSE, file, 0, 0, 0, 0);
+void close(int fd) {
+ call(SC_CLOSE, fd, 0, 0, 0, 0);
}
-int read(FILE file, size_t offset, size_t len, char *buffer) {
- return call(SC_READ, file, offset, len, (unsigned) buffer, 0);
+int read(int fd, size_t offset, size_t len, char *buffer) {
+ return call(SC_READ, fd, offset, len, (unsigned) buffer, 0);
}
-int write(FILE file, size_t offset, size_t len, const char* buffer) {
- return call(SC_WRITE, file, offset, len, (unsigned) buffer, 0);
+int write(int fd, size_t offset, size_t len, const char* buffer) {
+ return call(SC_WRITE, fd, offset, len, (unsigned) buffer, 0);
}
int link(const char* from, const char* to, int mode) {