diff options
author | Alex AUVOLAT <alexis211@gmail.com> | 2013-06-08 23:09:52 +0200 |
---|---|---|
committer | Alex AUVOLAT <alexis211@gmail.com> | 2013-06-08 23:09:52 +0200 |
commit | 4d65fcb9a8b6c7c6fd5a3390c46a96d11b6a80d4 (patch) | |
tree | c193acf64ff2db985f6664f161cf586c3caeb684 /src/user/lib | |
parent | eae9997d3c2dbaef53022ddabe61c1800a619499 (diff) | |
download | TCE-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')
29 files changed, 602 insertions, 709 deletions
diff --git a/src/user/lib/fwik/Makefile b/src/user/lib/fwik/Makefile deleted file mode 100644 index c99b288..0000000 --- a/src/user/lib/fwik/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -Out = _fwik.o -Obj = String.o io/Node.o io/Term.o io/Dir.o io/IOStream.o main.o - -ExtObj = $(SrcPath)/user/lib/libc/_libc.o - -include $(SrcPath)/common.make - -CFLAGS += -I$(SrcPath)/include -I$(SrcPath)/user/lib/libc/include -I$(SrcPath)/user/lib/fwik/include - -LDFLAGS += -r - diff --git a/src/user/lib/fwik/String.cpp b/src/user/lib/fwik/String.cpp deleted file mode 100644 index e3455e3..0000000 --- a/src/user/lib/fwik/String.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include <String.h> -#include <string.h> - -String::String() { - ptr = 0; - len = 0; -} - -String::String(const String &other) { - len = other.len; - if (len == 0) { - ptr = 0; - } else { - ptr = (char*)malloc(len + 1); - libc::memcpy(ptr, other.ptr, len + 1); - } -} - -String::String(const char* from) { - len = (from == 0 ? 0 : libc::strlen(from)); - if (len == 0) { - ptr = 0; - } else { - ptr = (char*)malloc(len + 1); - libc::memcpy(ptr, from, len + 1); - } -} - -String::String(const char* from, int l) { - len = l; - if (len < 0) len = 0; - if (len == 0) { - ptr = 0; - } else { - ptr = (char*)malloc(len + 1); - libc::memcpy(ptr, from, len); - ptr[len] = 0; - } -} - -String::String(char c, int count) { - len = count; - if (len == 0) { - ptr = 0; - } else { - ptr = (char*)malloc(len + 1); - libc::memset(ptr, c, len); - ptr[len] = 0; - } -} - -String::~String() { - if (ptr != 0) free(ptr); -} - -void String::operator=(const String &other) { - if (ptr != 0) free(ptr); - len = other.len; - if (len == 0) { - ptr = 0; - } else { - ptr = (char*)malloc(len + 1); - libc::memcpy(ptr, other.ptr, len + 1); - } -} - -void String::operator=(const char* from) { - if (ptr != 0) free(ptr); - len = (from == 0 ? 0 : libc::strlen(from)); - if (len == 0) { - ptr = 0; - } else { - ptr = (char*)malloc(len + 1); - libc::memcpy(ptr, from, len + 1); - } -} - -const char* String::c_str() const { - if (ptr == 0) return ""; - return ptr; -} - -bool String::operator==(const String& other) const { - if (len != other.len) return false; - for (int i = 0; i < len; i++) if (ptr[i] != other.ptr[i]) return false; - return true; -} - -bool String::operator==(const char* other) const { - if (other == 0) return (len == 0); - if (len != libc::strlen(other)) return false; - for (int i = 0; i < len; i++) if (ptr[i] != other[i]) return false; - return true; -} - -bool String::operator<(const String& other) const { - for (int i = 0; i < len && i < other.len; i++) { - if (ptr[i] > other.ptr[i]) return false; - if (ptr[i] < other.ptr[i]) return true; - } - if (len < other.len) return true; - return false; -} - -static char crap; -char &String::operator[](int pos) { - if (pos >= 0 && pos < len) return ptr[pos]; - crap = 0; - return crap; -} - -char String::operator[](int pos) const { - if (pos >= 0 && pos < len) return ptr[pos]; - return 0; -} - -String String::substr(int start, int count) const { - if (start + count > len) count = len - start; - return String(ptr + start, count); -} - -String String::operator+(const String& other) const { - String ret(' ', len + other.len); - libc::memcpy(ret.ptr, ptr, len); - libc::memcpy(ret.ptr + len, other.ptr, other.len); - return ret; -} - -void String::operator+=(const String& other) { - if (other.len == 0) return; - int newlen = len + other.len; - char* newptr = (char*)malloc(newlen + 1); - libc::memcpy(newptr, ptr, len); - libc::memcpy(newptr+len, other.ptr, other.len); - newptr[newlen] = 0; - free(ptr); - ptr = newptr; - len = newlen; -} - -void String::operator+=(char c) { - char* newptr = (char*)malloc(len + 2); - libc::memcpy(newptr, ptr, len); - newptr[len] = c; - len++; - newptr[len] = 0; - free(ptr); - ptr = newptr; -} - -String String::dec(int i) { - char b[16]; - const char *e = libc::format_int(b, i); - return String(b, e - b); -} - -String String::hex(uint32_t v) { - char b[16]; - const char *e = libc::format_hex(b, v); - return String(b, e - b); -} - -String String::sprintf(const char* format, ...) { - va_list ap; - va_start(ap, format); - va_list ap2; - va_copy(ap2, ap); - - String ret; - ret.len = libc::printf_str_len(format, ap2); - va_end(ap2); - ret.ptr = (char*)malloc(ret.len + 1); - ret.len = libc::vsprintf(ret.ptr, format, ap); - va_end(ap); - return ret; -} diff --git a/src/user/lib/fwik/include/IO/Dir.h b/src/user/lib/fwik/include/IO/Dir.h deleted file mode 100644 index bbfe3ed..0000000 --- a/src/user/lib/fwik/include/IO/Dir.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef DEF_FWIK_IO_DIR_H -#define DEF_FWIK_IO_DIR_H - -#include "Node.h" -#include <String.h> - -class Dir : public Node { - void _init(); - - public: - int pos; - - Dir(FILE f); - Dir(const char* file, int mode); - Dir(const Node &n); - virtual ~Dir(); - - String read_ent(); - - virtual Dir* as_dir() { return this; } -}; - -#endif - diff --git a/src/user/lib/fwik/include/IO/IOStream.h b/src/user/lib/fwik/include/IO/IOStream.h deleted file mode 100644 index 2e33268..0000000 --- a/src/user/lib/fwik/include/IO/IOStream.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef DEF_FWIK_IO_IOSTREAM_H -#define DEF_FWIK_IO_IOSTREAM_H - -#include "Term.h" - -#include <String.h> - -class IOStream { - public: - Term *term; - - IOStream() : term(0) {} - IOStream(Term *t) : term(t) {} - - void print(const char* str); - void printf(const char* fmt, ...); - String readln(); - - IOStream &operator<<(const char* s) { - print(s); - return *this; - } - IOStream &operator<<(const String& s) { - print(s.c_str()); - return *this; - } - IOStream &operator<<(int i) { - printf("%d", i); - return *this; - } - IOStream &operator<<(void* p) { - printf("%p", p); - return *this; - } -}; - -extern IOStream stdio; - -#endif diff --git a/src/user/lib/fwik/include/IO/Node.h b/src/user/lib/fwik/include/IO/Node.h deleted file mode 100644 index 6b5b063..0000000 --- a/src/user/lib/fwik/include/IO/Node.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef DEF_FWIK_IO_NODE_H -#define DEF_FWIK_IO_NODE_H - -#include <tce/syscall.h> -#include <tce/vfs.h> -#include <stdio.h> -#include <cpp.h> - -#include <String.h> - -class Term; -class Dir; -class Node { - public: - FILE fd; - file_info info; - int error; // will be 0 if this is a valid file descriptor - - Node(FILE f); - Node(const char* filename, int mode); - Node(FILE parent, const char* filename, int mode); - virtual ~Node() {} - - void close(); - - virtual Term* as_term() { return 0; } - virtual Dir* as_dir() { return 0; } -}; - -String path_cat(const String &a, const String &b, bool trailing_slash = true); - -#endif diff --git a/src/user/lib/fwik/include/IO/Term.h b/src/user/lib/fwik/include/IO/Term.h deleted file mode 100644 index 5b8aba3..0000000 --- a/src/user/lib/fwik/include/IO/Term.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef DEF_FWIK_IO_TERM_H -#define DEF_FWIK_IO_TERM_H - -#include <stdio.h> -#include "Node.h" -#include <String.h> - -#include <readline.h> - -class Term : public Node { - int w, h; - - readline_history hist; - - void _init(); - - public: - Term(FILE f); - Term(const char* filename, int mode); - Term(const Node &n); - virtual ~Term(); - - virtual void print(const char *s); - virtual void printf(const char* fmt, ...); - virtual void vprintf(const char* fmt, va_list ap); - virtual String readln(); - String readline(); - - virtual Term* as_term() { return this; } -}; - -#endif - diff --git a/src/user/lib/fwik/include/String.h b/src/user/lib/fwik/include/String.h deleted file mode 100644 index 59fa0b6..0000000 --- a/src/user/lib/fwik/include/String.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef DEF_FWIK_STRING_H -#define DEF_FWIK_STRING_H - -#include <cpp.h> - -class String { - private: - char *ptr; // zero-terminated for internal purposes. - int len; - - public: - String(); - String(const String& other); - String(const char* ptr); - String(const char* ptr, int len); - String(char c, int count); - ~String(); - void operator=(const String &string); - void operator=(const char* ptr); - - const char* c_str() const; - - bool operator==(const String& other) const; - bool operator==(const char* other) const; - bool operator<(const String& other) const; - char &operator[](int pos); - char operator[](int pos) const; - - int size() const { return len; } - operator bool() const { return len != 0; } - String substr(int start, int count) const; - - String operator+(const String& other) const; - void operator+=(const String& other); - void operator+=(char c); - - static String dec(int i); - static String hex(uint32_t v); - static String sprintf(const char* format, ...); -}; - -#endif diff --git a/src/user/lib/fwik/include/cpp.h b/src/user/lib/fwik/include/cpp.h deleted file mode 100644 index 5b66ba1..0000000 --- a/src/user/lib/fwik/include/cpp.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef DEF_FWIK_CPPSUPPORT_H -#define DEF_FWIK_CPPSUPPORT_H - -#include <stdlib.h> - -inline void* operator new(size_t, void* p) throw() { return p; } -inline void* operator new[](size_t, void* p) throw() { return p; } -inline void operator delete (void*, void*) throw() { }; -inline void operator delete[](void*, void*) throw() { }; - -inline void* operator new (size_t size) { return malloc(size); } -inline void* operator new[] (size_t size) { return malloc(size); } -inline void operator delete (void* ptr) { return free(ptr); } -inline void operator delete[] (void* ptr) { return free(ptr); } - -#endif diff --git a/src/user/lib/fwik/io/Dir.cpp b/src/user/lib/fwik/io/Dir.cpp deleted file mode 100644 index cfcc77b..0000000 --- a/src/user/lib/fwik/io/Dir.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include <IO/Dir.h> - -Dir::Dir(const Node &n) : Node(n) { - _init(); -} - -Dir::Dir(FILE f) : Node(f) { - _init(); - if (error == E_INVALID_TYPE) libc::close(fd); -} - -Dir::Dir(const char* filename, int mode) : Node(filename, mode) { - _init(); - if (error == E_INVALID_TYPE) libc::close(fd); -} - -void Dir::_init() { - if (error < 0) return; - pos = 0; - if ((info.type & FT_DIR) == 0) { - error = E_INVALID_TYPE; - } -} - -Dir::~Dir() { -} - -String Dir::read_ent() { - char buf[256]; - int l = libc::read(fd, pos, 256, buf); - if (l > 0) { - pos++; - return String(buf, l); - } else { - return ""; - } -} diff --git a/src/user/lib/fwik/io/IOStream.cpp b/src/user/lib/fwik/io/IOStream.cpp deleted file mode 100644 index 9d13251..0000000 --- a/src/user/lib/fwik/io/IOStream.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include <IO/IOStream.h> - -void IOStream::print(const char* str) { - if (term == 0) return; - term->print(str); -} - -void IOStream::printf(const char* fmt, ...) { - if (term == 0) return; - va_list ap; - va_start(ap, fmt); - term->vprintf(fmt, ap); - va_end(ap); -} - -String IOStream::readln() { - if (term == 0) return ""; - return term->readln(); -} diff --git a/src/user/lib/fwik/io/Node.cpp b/src/user/lib/fwik/io/Node.cpp deleted file mode 100644 index 5585aa8..0000000 --- a/src/user/lib/fwik/io/Node.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include <IO/Node.h> - -Node::Node(FILE f) { - fd = f; - error = libc::statf(f, &info); -} - -Node::Node(const char* filename, int mode) { - fd = libc::open(filename, mode); - if (fd < 0) { - if (fd != E_NOT_FOUND) error = libc::stat(filename, &info); - } else { - int i = libc::statf(fd, &info); - error = i; - if (error < 0) libc::close(fd); - } -} - -Node::Node(FILE parent, const char* filename, int mode) { - fd = libc::open_relative(parent, filename, mode); - if (fd < 0) { - if (fd != E_NOT_FOUND) error = libc::stat_relative(parent, filename, &info); - } else { - int i = libc::statf(fd, &info); - error = i; - if (error < 0) libc::close(fd); - } -} - -void Node::close() { - if (error == 0) libc::close(fd); - error = E_INVALID_FD; -} - -//////// - -static 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 (libc::strcmp(member, ".") == 0) { - char *i = member; - while (1) { - i[0] = i[2]; - if (i[0] == 0) break; - i++; - } - } else if (libc::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++; - } - } -} - -String path_cat(const String &a, const String &b, bool trailing_slash) { - int len, la = a.size(), lb = b.size(); - if (b[0] == '/') { - len = lb + 2; - } else { - len = la + lb + 3; - } - char buf[len]; - if (b[0] == '/') { - libc::memcpy(buf, b.c_str(), lb); - if (buf[lb-1] != '/') { - buf[lb++] = '/'; - } - buf[lb] = 0; - } else { - libc::memcpy(buf, a.c_str(), la); - if (buf[la-1] != '/') { - buf[la++] = '/'; - } - libc::memcpy(buf + la, b.c_str(), lb); - if (buf[la + lb - 1] != '/') { - buf[la + lb] = '/'; - lb++; - } - buf[la + lb] = 0; - } - simplify_path(buf); - if (!trailing_slash) { - int l = libc::strlen(buf); - if (buf[l-1] == '/') buf[l-1] = 0; - } - return String(buf); -} diff --git a/src/user/lib/fwik/io/Term.cpp b/src/user/lib/fwik/io/Term.cpp deleted file mode 100644 index f8f686e..0000000 --- a/src/user/lib/fwik/io/Term.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include <IO/Term.h> - -Term::Term(const Node &n) : Node(n) { - _init(); -} - -Term::Term(FILE f) : Node(f) { - _init(); - if (error E_INVALID_TYPE) libc::close(fd); -} - -Term::Term(const char* filename, int mode) : Node(filename, mode) { - _init(); - if (error == E_INVALID_TYPE) libc::close(fd); -} - -void Term::_init() { - if (error < 0) return; - if (info.type & FT_TERMINAL) { - w = info.size >> 16; - h = info.size & 0xFFFF; - } else { - error = E_INVALID_TYPE; - } - hist.str = 0; - hist.max = 12; -} - -Term::~Term() { - if (hist.str != 0) { - for (int i = 0; i < hist.max; i++) { - if (hist.str[i] != 0) free(hist.str[i]); - } - free(hist.str); - } -} - -void Term::print(const char *s) { - libc::fprint(fd, s); -} - -void Term::printf(const char* fmt, ...) { - va_list ap; - va_start(ap, fmt); - libc::vfprintf(fd, fmt, ap); - va_end(ap); -} - -void Term::vprintf(const char* fmt, va_list ap) { - libc::vfprintf(fd, fmt, ap); -} - -String Term::readln() { - char *s = libc::freadln(fd); - String ret(s); - free(s); - return ret; -} - -String Term::readline() { - return String(libc::freadline(fd, &hist)); -} diff --git a/src/user/lib/fwik/main.cpp b/src/user/lib/fwik/main.cpp deleted file mode 100644 index e7c40c4..0000000 --- a/src/user/lib/fwik/main.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include <IO/IOStream.h> -#include <stdio.h> -#include <cpp.h> -#include <String.h> - -IOStream stdio; - -int Main(String *args); // FWIK app main - -extern "C" int main(char **args) { - stdio.term = 0; - - Node zero(libc::term); - if (zero.info.type & FT_TERMINAL) { - stdio.term = new Term(zero); - } - - int argc = 0; - while (args[argc] != 0) argc++; - String s_args[argc+1]; - for (int i = 0; i < argc; i++) s_args[i] = args[i]; - - return Main(s_args); -} - - -// C++ support - -//Enables pure virtual functions -extern "C" void __cxa_pure_virtual() { - //do nothing -} -//Enables global objects -void *__dso_handle; -extern "C" int __cxa_atexit(void (*f)(void*), void *p, void *d) { return 0; } - - 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) { |