summaryrefslogtreecommitdiff
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
parenteae9997d3c2dbaef53022ddabe61c1800a619499 (diff)
downloadTCE-4d65fcb9a8b6c7c6fd5a3390c46a96d11b6a80d4.tar.gz
TCE-4d65fcb9a8b6c7c6fd5a3390c46a96d11b6a80d4.zip
All FWIK is deleted. YOSH is now pure C. Not-working KBASIC included.
-rw-r--r--Makefile10
-rw-r--r--src/common.make2
-rw-r--r--src/include/errno.h2
-rw-r--r--src/include/tce/syscalls.h5
-rw-r--r--src/include/tce/vfs.h2
-rw-r--r--src/kernel/config.h4
-rw-r--r--src/kernel/core/sys.cpp8
-rw-r--r--src/kernel/task/task.cpp10
-rw-r--r--src/kernel/task/task.h6
-rw-r--r--src/kernel/ui/vt.cpp41
-rw-r--r--src/kernel/ui/vt.h2
-rw-r--r--src/kernel/vfs/node.h3
-rw-r--r--src/user/app/fwik.make6
-rw-r--r--src/user/app/init/main.c4
-rw-r--r--src/user/app/kbasic/Makefile9
-rw-r--r--src/user/app/kbasic/basic.h75
-rw-r--r--src/user/app/kbasic/commands.c103
-rw-r--r--src/user/app/kbasic/control.c511
-rw-r--r--src/user/app/kbasic/expr.c153
-rw-r--r--src/user/app/kbasic/kbasic.txt19
-rw-r--r--src/user/app/kbasic/lex.c197
-rw-r--r--src/user/app/kbasic/main.c55
-rw-r--r--src/user/app/kbasic/pppg.bas14
-rw-r--r--src/user/app/kbasic/tables.bas15
-rw-r--r--src/user/app/kbasic/var.c19
-rw-r--r--src/user/app/led/main.c8
-rw-r--r--src/user/app/prime/main.c2
-rw-r--r--src/user/app/test/main.c2
-rw-r--r--src/user/app/yosh/Makefile2
-rw-r--r--src/user/app/yosh/main.c292
-rw-r--r--src/user/app/yosh/main.cpp271
-rw-r--r--src/user/lib/fwik/Makefile11
-rw-r--r--src/user/lib/fwik/String.cpp176
-rw-r--r--src/user/lib/fwik/include/IO/Dir.h24
-rw-r--r--src/user/lib/fwik/include/IO/IOStream.h39
-rw-r--r--src/user/lib/fwik/include/IO/Node.h32
-rw-r--r--src/user/lib/fwik/include/IO/Term.h33
-rw-r--r--src/user/lib/fwik/include/String.h42
-rw-r--r--src/user/lib/fwik/include/cpp.h16
-rw-r--r--src/user/lib/fwik/io/Dir.cpp37
-rw-r--r--src/user/lib/fwik/io/IOStream.cpp19
-rw-r--r--src/user/lib/fwik/io/Node.cpp118
-rw-r--r--src/user/lib/fwik/io/Term.cpp62
-rw-r--r--src/user/lib/fwik/main.cpp37
-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
-rw-r--r--src/user/link.ld2
61 files changed, 2116 insertions, 1049 deletions
diff --git a/Makefile b/Makefile
index 947874a..c44c64f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,10 @@
.PHONY: clean, mrproper, Init.rfs, floppy, commit
-Projects = tools/makeinitrd kernel user/lib/libc user/lib/fwik user/app/init user/app/test user/app/yosh user/app/prime user/app/led
+Projects = tools/makeinitrd kernel
+Projects += user/lib/libc
+Projects += user/app/init user/app/test user/app/prime user/app/led
+Projects += user/app/kbasic
+Projects += user/app/yosh
QemuCmd = qemu-system-i386
BasePath = $(shell pwd)
@@ -36,7 +40,7 @@ commit: mrproper
git commit -a; exit 0
git push origin
-$(Cdrom): menu_cdrom.lst src/kernel/kernel.elf src/user/app/test/test.elf src/user/app/init/init.elf src/user/app/yosh/yosh.elf src/user/app/prime/prime.elf src/user/app/led/led.elf
+$(Cdrom): menu_cdrom.lst src/kernel/kernel.elf src/user/app/test/test.elf src/user/app/init/init.elf src/user/app/yosh/yosh.elf src/user/app/prime/prime.elf src/user/app/led/led.elf src/user/app/kbasic/kbasic.elf
mkdir -p cdrom/boot/grub
if [ ! -e cdrom/boot/grub/stage2_eltorito ]; then \
echo "Please copy grub's stage2_eltorito to cdrom/boot/grub."; \
@@ -49,11 +53,13 @@ $(Cdrom): menu_cdrom.lst src/kernel/kernel.elf src/user/app/test/test.elf src/us
cp src/user/app/yosh/yosh.elf cdrom; strip cdrom/yosh.elf
cp src/user/app/prime/prime.elf cdrom; strip cdrom/prime.elf
cp src/user/app/led/led.elf cdrom; strip cdrom/led.elf
+ cp src/user/app/kbasic/kbasic.elf cdrom; strip cdrom/kbasic.elf
src/tools/makeinitrd/makeinitrd cdrom/initrd \
cdrom/test.elf:/bin/test \
cdrom/yosh.elf:/bin/yosh \
cdrom/prime.elf:/bin/prime \
cdrom/led.elf:/bin/led \
+ cdrom/kbasic.elf:/bin/kbasic \
README:/readme
genisoimage -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 \
-boot-info-table -input-charset ascii -A TCE -o $(Cdrom) cdrom
diff --git a/src/common.make b/src/common.make
index 4ffb6c6..be30752 100644
--- a/src/common.make
+++ b/src/common.make
@@ -3,7 +3,7 @@
# ============== ENVIRONMENT VARIABLES
CC = i586-elf-gcc
-CFLAGS = -m32 -nostdlib -nostdinc -nostartfiles -nodefaultlibs -fno-builtin -ffreestanding -fno-stack-protector -Wall -Werror -g -Wno-error=main
+CFLAGS = -m32 -nostdlib -nostdinc -nostartfiles -nodefaultlibs -fno-builtin -ffreestanding -fno-stack-protector -Wall -Werror -Wno-error=main
CCFLAGS =
CXX = i586-elf-g++
CXXFLAGS = -fno-rtti -fno-exceptions -Wno-write-strings -Wno-main -Wno-error=unused-parameter
diff --git a/src/include/errno.h b/src/include/errno.h
index fe60d81..098bcc1 100644
--- a/src/include/errno.h
+++ b/src/include/errno.h
@@ -8,7 +8,7 @@
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
-#define EIO 5 /* I/O error */
+#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
diff --git a/src/include/tce/syscalls.h b/src/include/tce/syscalls.h
index c82cab7..f32c225 100644
--- a/src/include/tce/syscalls.h
+++ b/src/include/tce/syscalls.h
@@ -29,6 +29,11 @@
#define SC_WRITE 27
#define SC_LINK 28
+#define EX_PAGEFAULT 4000
+#define EX_EXCEPTION 4001
+#define EX_NOTHREADS 4002
+#define EX_INVALID 4003
+
// ERRORS
#define E_NOT_IMPLEMENTED -1 // could also mean that your request is nonsense
diff --git a/src/include/tce/vfs.h b/src/include/tce/vfs.h
index 8af3514..36e391f 100644
--- a/src/include/tce/vfs.h
+++ b/src/include/tce/vfs.h
@@ -3,8 +3,6 @@
#include <types.h>
-typedef int FILE;
-
typedef struct _file_info {
uint32_t type;
uint32_t dev_type;
diff --git a/src/kernel/config.h b/src/kernel/config.h
index 74d0933..b7f6a17 100644
--- a/src/kernel/config.h
+++ b/src/kernel/config.h
@@ -2,7 +2,7 @@
#define DEF_CONFIG_H
#define K_OS_NAME "T/CE"
-#define K_OS_VER "0.1.3"
-#define K_OS_CODENAME "FWIcKet"
+#define K_OS_VER "0.1.4"
+#define K_OS_CODENAME "VivaElC"
#endif
diff --git a/src/kernel/core/sys.cpp b/src/kernel/core/sys.cpp
index 32ed988..01a3c20 100644
--- a/src/kernel/core/sys.cpp
+++ b/src/kernel/core/sys.cpp
@@ -32,7 +32,7 @@ void stack_trace(size_t bp) {
uint32_t *stack = (uint32_t*)bp, i;
for (i = 0; i < 5 && (size_t)stack > K_HIGHHALF_ADDR && (size_t)stack < (bp + 0x8000); i++) {
*ke_vt << " | " << (size_t)stack;
- *ke_vt << "\tnext:" << stack[0] << "\t\tret:" << stack[1] << "\n";
+ *ke_vt << "\tnext:" << stack[0] << "\t\tret:" << stack[1] << " \n";
stack = (uint32_t*)stack[0];
}
}
@@ -40,8 +40,8 @@ void stack_trace(size_t bp) {
/* For internal use only. Used by panic and panic_assert. */
static void panic_do(char* file, int line) {
asm volatile("cli;");
- *ke_vt << "\n File:\t\t" << file << ":" << line;
- *ke_vt << "\nTrace:\n";
+ *ke_vt << " \n File:\t\t" << file << ":" << line;
+ *ke_vt << " \nTrace: \n";
size_t bp; asm volatile("mov %%ebp,%0" : "=r"(bp)); stack_trace(bp);
*ke_vt << "\n\t\tSystem halted -_-'";
asm volatile("hlt");
@@ -52,6 +52,7 @@ void panic(char* message, char* file, int line) {
ke_vt->fgcolor = TC_WHITE;
ke_vt->bgcolor = TC_BLUE;
ke_vt->outputTo(text_display);
+ *ke_vt << " * * * * * * * * * * * * * * * * * * * * * * * * * * ";
*ke_vt << "\nPANIC:\t" << message;
panic_do(file, line);
}
@@ -60,6 +61,7 @@ void panic_assert(char* assertion, char* file, int line) {
ke_vt->fgcolor = TC_WHITE;
ke_vt->bgcolor = TC_RED;
ke_vt->outputTo(text_display);
+ *ke_vt << " * * * * * * * * * * * * * * * * * * * * * * * * * * ";
*ke_vt << "\nASSERT FAILED:\t" << assertion;
panic_do(file, line);
}
diff --git a/src/kernel/task/task.cpp b/src/kernel/task/task.cpp
index 4a802b8..91f802d 100644
--- a/src/kernel/task/task.cpp
+++ b/src/kernel/task/task.cpp
@@ -119,10 +119,10 @@ uint32_t tasking_handleException(registers *regs) {
*ke_vt << "\n (PID " << current_thread->process->pid << ") ";
if (regs->int_no == 14) {
*ke_vt << ">>> Process exiting.\n";
- thread_exit_stackJmp(EX_PR_EXCEPTION);
+ thread_exit_stackJmp(EX_PAGEFAULT);
} else {
*ke_vt << ">>> Thread exiting.\n";
- thread_exit_stackJmp(EX_TH_EXCEPTION);
+ thread_exit_stackJmp(EX_EXCEPTION);
}
PANIC("This should never have happened. Please report this.");
return 0;
@@ -160,7 +160,7 @@ void thread_exit2(uint32_t reason) { //See EX_TH_* defines in task.h
process* pr;
if (th == 0 || th->process == 0) goto retrn;
pr = th->process;
- if ((reason == EX_TH_NORMAL || reason == EX_TH_EXCEPTION) && pr->thread_count > 1) {
+ if ((reason == EX_NOTHREADS || reason == EX_EXCEPTION) && pr->thread_count > 1) {
delete th;
} else {
pr->finish(reason);
@@ -188,12 +188,12 @@ void thread_exit_stackJmp(uint32_t reason) {
/* System call. Exit the current thread. */
void thread_exit() {
- thread_exit_stackJmp(EX_TH_NORMAL);
+ thread_exit_stackJmp(EX_NOTHREADS);
}
/* System call. Exit the current process. */
void process_exit(size_t retval) {
- if (retval == EX_TH_NORMAL || retval == EX_TH_EXCEPTION) retval = EX_PR_EXCEPTION;
+ if (retval == EX_EXCEPTION || retval == EX_NOTHREADS || retval == EX_PAGEFAULT) retval = EX_INVALID;
thread_exit_stackJmp(retval);
}
diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h
index fa748c2..5cd3fb2 100644
--- a/src/kernel/task/task.h
+++ b/src/kernel/task/task.h
@@ -15,14 +15,12 @@
#define PL_USER 1
#define PL_KERNEL 0
-#define EX_TH_NORMAL 0x10000 //ERROR code : just one thread exits, because it has to
-#define EX_TH_EXCEPTION 0x10001 //ERROR code : just one thread exits, because of an unhandled exception
-#define EX_PR_EXCEPTION 0x10002 //ERROR code : all process finishes, because of an unhandled exception
-
#define USER_STACK_SIZE 0x10000 //64k, but pages will be mapped one by one as they are used
typedef void (*thread_entry)(void*);
+typedef int FILE; // DUPLICATE FROM vfs/node.h
+
class thread;
class node;
class process {
diff --git a/src/kernel/ui/vt.cpp b/src/kernel/ui/vt.cpp
index 3bed897..6876806 100644
--- a/src/kernel/ui/vt.cpp
+++ b/src/kernel/ui/vt.cpp
@@ -18,7 +18,6 @@ vt::vt(node* parent, int ww, int hh) : node(parent, FT_TERMINAL) {
bgcolor = TC_BLACK;
output = 0;
cursor_visible = true;
- keyboard_echo = false;
csr_l = csr_c = 0;
kbd_buffer_filled = 0;
@@ -194,9 +193,12 @@ void vt::keyboardInput(keypress kp, keyboard* from) {
if ((kp.command == 0 || kp.command == KB_ENTER || kp.command == KB_TAB || kp.command == KB_BACKSPACE)
&& kp.character != 0 && kp.pressed) {
b[n++] = (char)kp.character;
- } else if (kp.command == KB_CMD_ALT && kp.character >= 64 && kp.character <= 126 && kp.pressed) {
+ } else if ((kp.command & KB_CMD_ALT) && kp.character >= 64 && kp.character <= 126 && kp.pressed) {
b[n++] = 27;
b[n++] = kp.character;
+ } else if ((kp.command & KB_CMD_CTRL) && kp.character >= 'A' && kp.character <= 'z' && kp.pressed) {
+ if (kp.character >= 'A' && kp.character <= 'Z') b[n++] = 1 + kp.character - 'A';
+ if (kp.character >= 'a' && kp.character <= 'z') b[n++] = 1 + kp.character - 'a';
} else if (kb_cmd_esc[kp.command & 0x3F] != 0 && kp.pressed) {
int i;
for (i = 0; kb_cmd_esc[kp.command & 0x3F][i] != 0; i++) {
@@ -330,10 +332,6 @@ int vt::write(size_t offset, size_t len, char* buffer) {
} else if (buffer[i] == 'p') { // restore cursor position
csr_l = save_csr_l;
csr_c = save_csr_c;
- } else if (buffer[i] == 'e') { // CUSTOM : enable keyboard echo
- keyboard_echo = true;
- } else if (buffer[i] == 'h') { // CUSTOM : disable keyboard echo
- keyboard_echo = false;
} else if (buffer[i] == '?') {
if (buffer[++i] == '2' && buffer[++i] == '5') {
if (buffer[++i] == 'l') cursor_visible = false;
@@ -361,38 +359,17 @@ int vt::read(size_t offset, size_t len, char* buffer) {
unsigned c = 0;
while (true) {
- bool end = false;
if (kbd_buffer_filled > 0) {
int r = 0;
- if (keyboard_echo) {
- for (; r < kbd_buffer_filled; r++) {
- if (kbd_buffer[r] == '\b') {
- if (c > 0) {
- c--;
- put('\b');
- }
- } else if (kbd_buffer[r] == '\n') {
- buffer[c++] = '\n';
- c++;
- put('\n');
- end = true;
- break;
- } else if (kbd_buffer[r] >= ' ') {
- buffer[c++] = kbd_buffer[r];
- put(buffer[c]);
- }
- if (c == len) break;
- }
- } else {
- while (r < kbd_buffer_filled && c < len) {
- buffer[c++] = kbd_buffer[r++];
- }
- end = true;
+ while (r < kbd_buffer_filled && c < len) {
+ buffer[c++] = kbd_buffer[r++];
}
+
memcpy(kbd_buffer + r, kbd_buffer, (kbd_buffer_filled - r));
kbd_buffer_filled -= r;
+
+ return c;
}
- if (end || c == len) return c;
if (kbd_waiter != 0) return c;
kbd_waiter = current_thread;
diff --git a/src/kernel/ui/vt.h b/src/kernel/ui/vt.h
index a29716f..8a169b4 100644
--- a/src/kernel/ui/vt.h
+++ b/src/kernel/ui/vt.h
@@ -19,7 +19,7 @@ class vt : public node {
vt_char *text;
void put_at(int l, int c, int ch);
- bool cursor_visible, keyboard_echo;
+ bool cursor_visible;
int kbd_buffer_filled;
char kbd_buffer[KBD_BUFFER_SIZE];
diff --git a/src/kernel/vfs/node.h b/src/kernel/vfs/node.h
index 2ebf93b..3b1c700 100644
--- a/src/kernel/vfs/node.h
+++ b/src/kernel/vfs/node.h
@@ -4,6 +4,7 @@
#include <tce/vfs.h>
#include <tce/syscalls.h>
+
#include <task/task.h>
class display;
@@ -38,6 +39,8 @@ node* vfs_find(node* root, char* filename);
extern node *root, *dot_dev, *dot_ui;
+typedef int FILE; // file descriptor type, DIFFERENT FROM FILE TYPE IN USERLAND !!!
+
// syscall interface
FILE open(char* filename, int mode);
FILE open_relative(FILE root, char* filename, int mode);
diff --git a/src/user/app/fwik.make b/src/user/app/fwik.make
deleted file mode 100644
index 292440d..0000000
--- a/src/user/app/fwik.make
+++ /dev/null
@@ -1,6 +0,0 @@
-ExtObj = $(SrcPath)/user/lib/fwik/_fwik.o
-
-include $(SrcPath)/common.make
-
-CFLAGS += -I $(SrcPath)/include -I $(SrcPath)/user/lib/libc/include -I $(SrcPath)/user/lib/fwik/include
-LDFLAGS += -T $(SrcPath)/user/link.ld
diff --git a/src/user/app/init/main.c b/src/user/app/init/main.c
index 92fb8f7..bd0b3bf 100644
--- a/src/user/app/init/main.c
+++ b/src/user/app/init/main.c
@@ -1,8 +1,8 @@
#include <tce/syscall.h>
#include <stdio.h>
-int main(char **args) {
- FILE home_term = open("/.ui/home", 0);
+int main(int argc, char **args) {
+ int home_term = open("/.ui/home", 0);
int i, pid;
if (home_term < 0) return -1;
diff --git a/src/user/app/kbasic/Makefile b/src/user/app/kbasic/Makefile
new file mode 100644
index 0000000..22bf991
--- /dev/null
+++ b/src/user/app/kbasic/Makefile
@@ -0,0 +1,9 @@
+Obj = main.o lex.o control.o commands.o var.o expr.o
+Out = kbasic.elf
+
+
+include $(SrcPath)/user/app/common.make
+
+LDFLAGS += -Map kbasic.map
+CFLAGS += -Wno-error=missing-braces
+
diff --git a/src/user/app/kbasic/basic.h b/src/user/app/kbasic/basic.h
new file mode 100644
index 0000000..b3491da
--- /dev/null
+++ b/src/user/app/kbasic/basic.h
@@ -0,0 +1,75 @@
+/* A tiny BASIC interpreter */
+
+/*
+ Thank the Internet for providing me with this program.
+ Please report any bugs/security holes to: katchup@adnab.fr.nf
+*/
+
+#ifndef DEF_BASIC_H
+#define DEF_BASIC_H
+
+
+// Token types
+#define DELIMITER 1
+#define VARIABLE 2
+#define NUMBER 3
+#define COMMAND 4
+#define STRING 5
+#define QUOTE 6
+
+// Keywords
+#define EOL 98 // Special characters
+#define FINISHED 99
+#define IF 1 // Control structures
+#define THEN 2
+#define FOR 3
+#define NEXT 4
+#define TO 5
+#define GOTO 6
+#define GOSUB 7
+#define RETURN 8
+#define END 9
+#define EXEC 10
+#define LOAD 11
+#define RUN 12
+#define LIST 13
+#define PRINT 20 // Built-in commands
+#define INPUT 21
+#define RND 50 // Built-in functions
+
+// Buffer size definitions
+#define TOK_LEN 80
+#define LAB_LEN 10 // Control structures
+#define NUM_LAB 100
+#define FOR_NEST 25
+#define SUB_NEST 25
+
+// Lexer
+extern char *program; // Data for program
+extern char *prog_ip; // Program instructino pointer
+extern char token[TOK_LEN];
+extern int token_type, tok;
+int get_token();
+void putback();
+void find_eol();
+char *load_file(char *fname);
+
+// Data structures
+int* find_var(char *s); // returns a pointer to the variable
+
+// Program structure
+void init();
+extern char *interp_name; /* given by command line argument 0 */
+void load_program(char *); // load and scan labels
+void insert_line(char *l, int n); // add line to program
+int start(char *entry); // start execution at given point
+void serror(int);
+
+// BASIC commands
+void exec_print(), input();
+void assignment();
+void get_exp(int*);
+
+
+#endif
+
diff --git a/src/user/app/kbasic/commands.c b/src/user/app/kbasic/commands.c
new file mode 100644
index 0000000..f60f32a
--- /dev/null
+++ b/src/user/app/kbasic/commands.c
@@ -0,0 +1,103 @@
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "basic.h"
+
+/* Assign a variable a value. */
+void assignment()
+{
+ int *var;
+ int value;
+
+ /* get the variable name */
+ get_token();
+ if(!isalpha(*token)) {
+ serror(4);
+ return;
+ }
+
+ var = find_var(token);
+
+ /* get the equals sign */
+ get_token();
+ if(*token!='=') {
+ serror(3);
+ return;
+ }
+
+ /* get the value to assign to var */
+ get_exp(&value);
+
+ /* assign the value */
+ *var = value;
+}
+
+
+
+/* Execute a simple version of the BASIC PRINT statement */
+void exec_print()
+{
+ int answer;
+ int len=0, spaces;
+ char last_delim;
+
+ do {
+ get_token(); /* get next list item */
+ if(tok==EOL || tok==FINISHED) break;
+ if(token_type==QUOTE) { /* is string */
+ printf("%s", token);
+ len += strlen(token);
+ get_token();
+ }
+ else { /* is expression */
+ putback();
+ get_exp(&answer);
+ get_token();
+ len += printf("%d", answer);
+ }
+ last_delim = *token;
+
+ if(*token==';') {
+ /* compute number of spaces to move to next tab */
+ spaces = 8 - (len % 8);
+ len += spaces; /* add in the tabbing position */
+ while(spaces) {
+ printf(" ");
+ spaces--;
+ }
+ }
+ else if(*token==',') /* do nothing */;
+ else if(tok!=EOL && tok!=FINISHED) serror(0);
+ } while (*token==';' || *token==',');
+
+ if(tok==EOL || tok==FINISHED) {
+ if(last_delim != ';' && last_delim!=',') printf("\n");
+ }
+ else serror(0); /* error is not , or ; */
+
+}
+
+/* Execute a simple form of the BASIC INPUT command */
+void input()
+{
+ int *var;
+ int tmp;
+
+ get_token(); /* see if prompt string is present */
+ if(token_type==QUOTE) {
+ printf("%s", token); /* if so, print it and check for comma */
+ get_token();
+ if(*token!=',') serror(1);
+ get_token();
+ }
+ else printf("? "); /* otherwise, prompt with / */
+
+ var = find_var(token); /* get the input var */
+
+ scanf("%d\n", var); /* read input */
+
+ /* flush input */
+ while ((tmp = getchar()) != '\n' && tmp != EOF);
+}
+
diff --git a/src/user/app/kbasic/control.c b/src/user/app/kbasic/control.c
new file mode 100644
index 0000000..1ab22ff
--- /dev/null
+++ b/src/user/app/kbasic/control.c
@@ -0,0 +1,511 @@
+#include <stdio.h>
+#include <string.h>
+// #include <sys/wait.h>
+// #include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <setjmp.h>
+
+#include "basic.h"
+
+struct label {
+ char name[LAB_LEN];
+ char *p; /* points to place to go in source file*/
+};
+struct for_stack {
+ int *var; /* counter variable */
+ int target; /* target value */
+ char *loc;
+};
+
+struct label label_table[NUM_LAB];
+
+char *gstack[SUB_NEST]; /* stack for gosub */
+struct for_stack fstack[FOR_NEST]; /* stack for FOR/NEXT loop */
+
+int ftos; /* index to top of FOR stack */
+int gtos; /* index to top of GOSUB stack */
+
+char *program, *prog_ip; /* holds expression to be analyzed */
+
+char *interp_name;
+
+jmp_buf e_buf; /* hold environment for longjmp() */
+
+char *find_label();
+void scan_labels();
+struct for_stack fpop();
+char *gpop();
+int get_next_label(char *);
+void fpush(struct for_stack);
+void gosub(), greturn(), gpush(char*), label_init();
+void exec_if(), exec_for(), next(), exec_goto();
+void exec_exec(), exec_load();
+void exec_list();
+
+/* initialize variables */
+void init() {
+ program = NULL;
+ prog_ip = NULL;
+ label_init();
+}
+
+/* Load program and scans labels */
+void load_program (char *p_buf) {
+ if (program != NULL) {
+ free(program);
+ }
+
+ program = p_buf;
+ scan_labels(); /* find the labels in the program */
+}
+
+/* Insert line at the right place of program */
+void insert_line(char *l, int n) {
+ char *a, *b, *p;
+ int i_n, t, k;
+
+
+ if (program == NULL) {
+ load_program(strdup(l));
+ } else {
+ int prog_l = strlen(program);
+
+ // lookup insert position
+ // find smallest label above line number
+ a = (n == 0 ? program : program + prog_l);
+ i_n = -1; b = program + prog_l;
+
+ for (t = 0; t < NUM_LAB; t++) {
+ if (label_table[t].name[0]) {
+ k = atoi(label_table[t].name);
+ if (k == n) {
+ a = label_table[t].p;
+ while (*a != '\n' && a > program) a--; // back to beginning of line
+ if (*a == '\n') a++;
+ }
+ if (k > n && (k < i_n || i_n == -1)) {
+ i_n = k;
+ b = label_table[t].p;
+ while (*b != '\n' && b > program) b--; // back to beginning of line
+ if (*b == '\n') b++;
+ if (b < a) a = b;
+ }
+ }
+ }
+
+ p = malloc(prog_l + strlen(l) + 3);
+
+ strncpy(p, program, (a - program)); // copy [0, a[
+ p[a - program] = 0;
+ // if l is an empty line, do not copy.
+ for (i_n = 0; l[i_n]; i_n++) {
+ if (!isdigit(l[i_n]) && l[i_n] != '\n' && l[i_n] != '\r') {
+ strcpy(p + (a - program), l); // copy l
+ break;
+ }
+ }
+ strcat(p + (a - program), b); // copy [b, end[
+
+ load_program(p); // reparse labels
+ }
+}
+
+/* start program execution at given entry point (not necessarily in loaded program)
+ return values :
+ - 0 : return on end of input
+ - 1 : return on error
+ - 2 : return on "END" statement
+ - 3 : return on "LOAD" statement
+*/
+int start(char *entry) {
+ ftos = 0; /* initialize the FOR stack index */
+ gtos = 0; /* initialize the GOSUB stack index */
+
+ prog_ip = entry;
+ if(setjmp(e_buf)) return 1; /* initialize the long jump buffer */
+
+ do {
+ token_type = get_token();
+ /* check for assignment statement */
+ if(token_type==VARIABLE) {
+ putback(); /* return the var to the input stream */
+ assignment(); /* must be assignment statement */
+ }
+ else /* is command */
+ switch(tok) {
+ case LIST:
+ exec_list();
+ break;
+ case PRINT:
+ exec_print();
+ break;
+ case GOTO:
+ exec_goto();
+ break;
+ case IF:
+ exec_if();
+ break;
+ case FOR:
+ exec_for();
+ break;
+ case NEXT:
+ next();
+ break;
+ case INPUT:
+ input();
+ break;
+ case GOSUB:
+ gosub();
+ break;
+ case RETURN:
+ greturn();
+ break;
+ case EXEC:
+ exec_exec();
+ break;
+ case LOAD:
+ exec_load();
+ return 3;
+ case RUN: // (re)start program at begining
+ ftos = gtos = 0;
+ prog_ip = program;
+ break;
+ case END: // end program execution
+ return 2;
+ }
+ } while (prog_ip != NULL && tok != FINISHED);
+
+ return 0;
+}
+
+/* display an error message */
+void serror(int error)
+{
+ static char *e[]= {
+ "syntax error",
+ "unbalanced parentheses",
+ "no expression present",
+ "equals sign expected",
+ "not a variable",
+ "Label table full",
+ "duplicate label",
+ "undefined label",
+ "THEN expected",
+ "TO expected",
+ "too many nested FOR loops",
+ "NEXT without FOR",
+ "too many nested GOSUBs",
+ "RETURN without GOSUB"
+ };
+ printf ("[near '%s' %d %d] E: %s\n", token, tok, token_type, e[error]);
+
+ longjmp(e_buf, 1); /* return to save point */
+ exit(0);
+
+}
+
+/* Find all labels. */
+void scan_labels()
+{
+ int addr;
+
+ label_init(); /* zero all labels */
+
+ if (program == 0) return; /* if no program is loaded, nothing to do. */
+
+ prog_ip = program; /* prog_ip will go through the program */
+
+ /* if the first token in the file is a label */
+ get_token();
+ if(token_type==NUMBER) {
+ strcpy(label_table[0].name,token);
+ label_table[0].p=prog_ip;
+ }
+
+ find_eol();
+ do {
+ get_token();
+ if(token_type==NUMBER) {
+ addr = get_next_label(token);
+ if(addr==-1 || addr==-2) {
+ (addr==-1) ?serror(5):serror(6);
+ }
+ strncpy(label_table[addr].name, token, LAB_LEN);
+ label_table[addr].name[LAB_LEN-1] = 0; // null terminate
+ label_table[addr].p = prog_ip; /* current point in program */
+ }
+ /* if not on a blank line, find next line */
+ if(tok!=EOL) find_eol();
+ } while(tok!=FINISHED);
+}
+
+/* Return index of next free position in label array.
+ A -1 is returned if the array is full.
+ A -2 is returned when duplicate label is found.
+ */
+int get_next_label(char *s)
+{
+ register int t;
+
+ for(t=0;t<NUM_LAB;++t) {
+ if(label_table[t].name[0]==0) return t;
+ if(!strcmp(label_table[t].name,s)) return -2; /* dup */
+ }
+
+ return -1;
+}
+
+/* Find location of given label. A null is returned if
+ label is not found; otherwise a pointer to the position
+ of the label is returned.
+ */
+char *find_label(char *s)
+{
+ register int t;
+
+ for(t=0; t<NUM_LAB; ++t)
+ if(!strcmp(label_table[t].name,s)) return label_table[t].p;
+ return '\0'; /* error condition */
+}
+
+/* Execute a GOTO statement. */
+void exec_goto()
+{
+
+ char *loc;
+
+ get_token(); /* get label to go to */
+ /* find the location of the label */
+ loc = find_label(token);
+ if(loc=='\0')
+ serror(7); /* label not defined */
+
+ else prog_ip=loc; /* start program running at that loc */
+}
+
+/* Initialize the array that holds the labels.
+ By convention, a null label name indicates that
+ array position is unused.
+ */
+void label_init()
+{
+ register int t;
+
+ for(t=0; t<NUM_LAB; ++t) label_table[t].name[0]='\0';
+}
+
+/* Execute an IF statement. */
+void exec_if()
+{
+ int x , y, cond;
+ char op;
+
+ get_exp(&x); /* get left expression */
+
+ get_token(); /* get the operator */
+ if(!strchr("=<>", *token)) {
+ serror(0); /* not a legal operator */
+ return;
+ }
+ op=*token;
+
+ get_exp(&y); /* get right expression */
+
+ /* determine the outcome */
+ cond = 0;
+ switch(op) {
+ case '<':
+ if(x<y) cond=1;
+ break;
+ case '>':
+ if(x>y) cond=1;
+ break;
+ case '=':
+ if(x==y) cond=1;
+ break;
+ }
+ if(cond) { /* is true so process target of IF */
+ get_token();
+ if(tok!=THEN) {
+ serror(8);
+ return;
+ }/* else program execution starts on next line */
+ }
+ else find_eol(); /* find start of next line */
+}
+
+/* Execute a FOR loop. */
+void exec_for()
+{
+ struct for_stack i;
+ int value;
+
+ get_token(); /* read the control variable */
+ if(!isalpha(*token)) {
+ serror(4);
+ return;
+ }
+
+ i.var=find_var(token); /* save its index */
+
+ get_token(); /* read the equals sign */
+ if(*token!='=') {
+ serror(3);
+ return;
+ }
+
+ get_exp(&value); /* get initial value */
+
+ *(i.var) = value;
+
+ get_token();
+ if(tok!=TO) serror(9); /* read and discard the TO */
+
+ get_exp(&i.target); /* get target value */
+
+ /* if loop can execute at least once, push info on stack */
+ if(value>=*(i.var)) {
+ i.loc = prog_ip;
+ fpush(i);
+ }
+ else /* otherwise, skip loop code altogether */
+ while(tok!=NEXT) get_token();
+}
+
+/* Execute a NEXT statement. */
+void next()
+{
+ struct for_stack i;
+
+ i = fpop(); /* read the loop info */
+
+ (*(i.var))++;
+ if(*(i.var)>i.target) return; /* all done */
+ fpush(i); /* otherwise, restore the info */
+ prog_ip = i.loc; /* loop */
+}
+
+/* Push function for the FOR stack. */
+void fpush(struct for_stack i)
+{
+ if(ftos>FOR_NEST)
+ serror(10);
+
+ fstack[ftos]=i;
+ ftos++;
+}
+
+struct for_stack fpop()
+{
+ ftos--;
+ if(ftos<0) serror(11);
+ return(fstack[ftos]);
+}
+
+/* Execute a GOSUB command. */
+void gosub()
+{
+ char *loc;
+
+ get_token();
+ /* find the label to call */
+ loc = find_label(token);
+ if(loc=='\0')
+ serror(7); /* label not defined */
+ else {
+ gpush(prog_ip); /* save place to return to */
+ prog_ip = loc; /* start program running at that loc */
+ }
+}
+
+/* Return from GOSUB. */
+void greturn()
+{
+ prog_ip = gpop();
+}
+
+/* GOSUB stack push function. */
+void gpush(char *s)
+{
+ gtos++;
+
+ if(gtos==SUB_NEST) {
+ serror(12);
+ return;
+ }
+
+ gstack[gtos]=s;
+
+}
+
+/* GOSUB stack pop function. */
+char *gpop()
+{
+ if(gtos==0) {
+ serror(13);
+ return 0;
+ }
+
+ return(gstack[gtos--]);
+}
+
+
+/* EXEC function
+ Forks and runs another instance of the interpreter
+ */
+void exec_exec() {
+
+ /* TODO
+ int pid;
+
+ get_token();
+ if (token_type==QUOTE) {
+ pid = fork();
+ if (pid < 0) {
+ printf("Error: could not fork.\n");
+ } else {
+ if (pid == 0) {
+ execlp(interp_name, interp_name, token, 0);
+ printf("Error: could not exec.\n");
+ exit(0);
+ } else {
+ wait(0);
+ }
+ }
+ get_token();
+ } else {
+ serror(0);
+ }
+ */
+ printf("EXEC not available.\n");
+}
+
+/* LOAD function
+ loads a program into interpreter and ends anything currently executing */
+void exec_load() {
+ char *p_buf;
+
+ get_token();
+ if (token_type==QUOTE) {
+ if (!(p_buf = load_file(token))) {
+ printf("Error: could not load file %s\n", token);
+ } else {
+ load_program(p_buf);
+ }
+ } else {
+ serror(0);
+ }
+}
+
+/* LIST function
+ dumps program source text */
+void exec_list() {
+ get_token();
+
+ if (program == NULL) {
+ printf("No program loaded.\n");
+ } else {
+ printf("%s", program);
+ }
+}
diff --git a/src/user/app/kbasic/expr.c b/src/user/app/kbasic/expr.c
new file mode 100644
index 0000000..3b8d558
--- /dev/null
+++ b/src/user/app/kbasic/expr.c
@@ -0,0 +1,153 @@
+#include <stdlib.h>
+
+#include "basic.h"
+
+void level2(int*), level3(int*), level4(int*), level5(int*), level6(int*), primitive(int*);
+void unary(char, int*), arith(char, int*, int*);
+
+/* Entry point into parser. */
+void get_exp(int *result)
+{
+ get_token();
+ if(!*token) {
+ serror(2);
+ return;
+ }
+ level2(result);
+ putback(); /* return last token read to input stream */
+}
+
+/* Add or subtract two terms. */
+void level2(int *result)
+{
+ register char op;
+ int hold;
+
+ level3(result);
+ while((op = *token) == '+' || op == '-') {
+ get_token();
+ level3(&hold);
+ arith(op, result, &hold);
+ }
+}
+
+/* Multiply or divide two factors. */
+void level3(int *result)
+{
+ register char op;
+ int hold;
+
+ level4(result);
+ while((op = *token) == '*' || op == '/' || op == '%') {
+ get_token();
+ level4(&hold);
+ arith(op, result, &hold);
+ }
+}
+
+/* Process integer exponent. */
+void level4(int *result)
+{
+ int hold;
+
+ level5(result);
+ if(*token== '^') {
+ get_token();
+ level4(&hold);
+ arith('^', result, &hold);
+ }
+}
+
+/* Is a unary + or -. */
+void level5(int *result)
+{
+ register char op;
+
+ op = 0;
+ if((token_type==DELIMITER) && (*token=='+' || *token=='-')) {
+ op = *token;
+ get_token();
+ }
+ level6(result);
+ if(op)
+ unary(op, result);
+}
+
+/* Process parenthesized expression. */
+void level6(int *result)
+{
+ if((*token == '(') && (token_type == DELIMITER)) {
+ get_token();
+ level2(result);
+ if(*token != ')')
+ serror(1);
+ get_token();
+ }
+ else
+ primitive(result);
+}
+
+/* Find value of number or variable. */
+void primitive(int *result)
+{
+
+ switch(token_type) {
+ case VARIABLE:
+ *result = *find_var(token);
+ get_token();
+ return;
+ case NUMBER:
+ *result = atoi(token);
+ get_token();
+ return;
+ case COMMAND:
+ switch(tok) {
+ case RND:
+ *result = rand();
+ get_token();
+ return;
+ }
+ default:
+ serror(0);
+ }
+}
+
+/* Perform the specified arithmetic. */
+void arith(char o, int *r, int *h)
+{
+ register int t, ex;
+
+ switch(o) {
+ case '-':
+ *r = *r-*h;
+ break;
+ case '+':
+ *r = *r+*h;
+ break;
+ case '*':
+ *r = *r * *h;
+ break;
+ case '/':
+ *r = (*r)/(*h);
+ break;
+ case '%':
+ t = (*r)/(*h);
+ *r = *r-(t*(*h));
+ break;
+ case '^':
+ ex = *r;
+ if(*h==0) {
+ *r = 1;
+ break;
+ }
+ for(t=*h-1; t>0; --t) *r = (*r) * ex;
+ break;
+ }
+}
+
+/* Reverse the sign. */
+void unary(char o, int *r)
+{
+ if(o=='-') *r = -(*r);
+}
+
diff --git a/src/user/app/kbasic/kbasic.txt b/src/user/app/kbasic/kbasic.txt
new file mode 100644
index 0000000..19131ed
--- /dev/null
+++ b/src/user/app/kbasic/kbasic.txt
@@ -0,0 +1,19 @@
+KBASIC commands
+
+EXEC "<filename.bas>" fork and run file in a new process
+LOAD "<filename.bas>" reset interpreter context and load file, ends all execution
+RUN start loaded program at begining
+END end execution of program
+LIST list program text
+
+GOTO <label>
+IF <a> [=><] <b> THEN <expr>
+GOSUB <label>
+RETURN
+FOR <var> = <a> to <b>
+NEXT
+
+PRINT
+INPUT
+
+RND
diff --git a/src/user/app/kbasic/lex.c b/src/user/app/kbasic/lex.c
new file mode 100644
index 0000000..055b502
--- /dev/null
+++ b/src/user/app/kbasic/lex.c
@@ -0,0 +1,197 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "basic.h"
+
+struct commands { /* keyword lookup table */
+ char command[20];
+ char tok;
+} table[] = { /* Commands must be entered lowercase */
+ {"print", PRINT}, /* in this table. */
+ {"input", INPUT},
+
+ {"if", IF},
+ {"then", THEN},
+ {"goto", GOTO},
+ {"for", FOR},
+ {"next", NEXT},
+ {"to", TO},
+ {"gosub", GOSUB},
+ {"return", RETURN},
+
+ {"end", END},
+ {"run", RUN},
+ {"load", LOAD},
+ {"list", LIST},
+ {"exec", EXEC},
+
+ {"rnd", RND},
+ {"", END} /* mark end of table */
+};
+
+char token[TOK_LEN];
+int token_type, tok;
+
+int look_up(char *s); // lookup keyword
+int iswhite(char c);
+int isdelim(char c);
+
+
+/* Load a file into a buffer. */
+char* load_file(char *fname) {
+ FILE *fp;
+ char *p;
+ int size;
+
+ if(!(fp=fopen(fname, "rb"))) return 0;
+
+ // Get file size
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ p = (char*)malloc(size + 2);
+ fseek(fp, 0, SEEK_SET);
+
+ // Read file contents
+ fread(p, size, 1, fp);
+ fclose(fp);
+
+ /* null terminate the program */
+ if (p[size-1] != '\n') p[size++] = '\n';
+ p[size] = 0;
+
+ return p;
+}
+
+
+/* Find the start of the next line. */
+void find_eol()
+{
+ while(*prog_ip!='\n' && *prog_ip!='\0') ++prog_ip;
+ if(*prog_ip) prog_ip++;
+}
+
+/* Get a token. */
+int get_token()
+{
+
+ register char *temp;
+
+ token_type=0; tok=0;
+ temp=token;
+
+ if(*prog_ip=='\0') { /* end of file */
+ *token=0;
+ tok = FINISHED;
+ return(token_type=DELIMITER);
+ }
+
+ while(iswhite(*prog_ip)) ++prog_ip; /* skip over white space */
+
+ if(*prog_ip=='\r') { /* crlf */
+ ++prog_ip; ++prog_ip;
+ tok = EOL; *token='\r';
+ token[1]='\n'; token[2]=0;
+ return (token_type = DELIMITER);
+ }
+ if (*prog_ip=='\n') { /* lf (unix newline) */
+ ++prog_ip;
+ tok = EOL; *token='\n'; token[1] = 0;
+ return (token_type = DELIMITER);
+ }
+
+ if(strchr("+-*^/%=;(),><", *prog_ip)){ /* delimiter */
+ *temp=*prog_ip;
+ prog_ip++; /* advance to next position */
+ temp++;
+ *temp=0;
+ return (token_type=DELIMITER);
+ }
+
+ if(*prog_ip=='"') { /* quoted string */
+ prog_ip++;
+ while(*prog_ip!='"'&& *prog_ip!='\r' && *prog_ip!='\n') {
+ if (temp - token < TOK_LEN - 1) *temp++=*prog_ip;
+ prog_ip++;
+ }
+ if(*prog_ip=='\r' || *prog_ip=='\n') serror(1);
+ prog_ip++;*temp=0;
+ return(token_type=QUOTE);
+ }
+
+ if(isdigit(*prog_ip)) { /* number */
+ while(!isdelim(*prog_ip)) {
+ if (temp - token < TOK_LEN - 1) *temp++=*prog_ip;
+ prog_ip++;
+ }
+ *temp = '\0';
+ return(token_type = NUMBER);
+ }
+
+ if(isalpha(*prog_ip)) { /* var or command */
+ while(!isdelim(*prog_ip)) {
+ if (temp - token < TOK_LEN - 1) *temp++=*prog_ip;
+ prog_ip++;
+ }
+ token_type=STRING;
+ }
+
+ *temp = '\0';
+
+ /* see if a string is a command or a variable */
+ if(token_type==STRING) {
+ tok=look_up(token); /* convert to internal rep */
+ if(!tok) token_type = VARIABLE;
+ else token_type = COMMAND; /* is a command */
+ }
+ return token_type;
+}
+
+
+
+/* Return a token to input stream. */
+void putback()
+{
+
+ char *t;
+
+ t = token;
+ for(; *t; t++) prog_ip--;
+}
+
+/* Look up a a token's internal representation in the
+ token table.
+ */
+int look_up(char *s)
+{
+ register int i;
+ char *p;
+
+ /* convert to lowercase */
+ p = s;
+ while(*p){ *p = tolower(*p); p++; }
+
+ /* see if token is in table */
+ for(i=0; *table[i].command; i++)
+ if(!strcmp(table[i].command, s)) return table[i].tok;
+ return 0; /* unknown command */
+}
+
+/* Return true if c is a delimiter. */
+int isdelim(char c)
+{
+ if(strchr(" ;,+-<>/*%^=()", c) || c==9 || c=='\r' || c=='\n' || c==0)
+ return 1;
+ return 0;
+}
+
+/* Return 1 if c is space or tab. */
+int iswhite(char c)
+{
+ if(c==' ' || c=='\t') return 1;
+ else return 0;
+}
+
+
+
diff --git a/src/user/app/kbasic/main.c b/src/user/app/kbasic/main.c
new file mode 100644
index 0000000..1003a7b
--- /dev/null
+++ b/src/user/app/kbasic/main.c
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <readline.h>
+
+#include "basic.h"
+
+int main(int argc, char **argv) {
+ char *p_buf;
+
+ srand(0); // not very usefull...
+
+ readline_history hist;
+ hist.str = 0; hist.max = 10;
+
+ interp_name = argv[0];
+ init();
+
+ if(argc == 2) {
+ /* load the program to execute */
+ if(!(p_buf = load_file(argv[1]))) exit(1);
+
+ load_program(p_buf);
+ start(p_buf);
+ } else if (argc == 1) {
+ printf("KBASIC 0.1\n"
+ "Press ^D to quit interpreter.\n\n");
+
+ for (;;) {
+ printf("> ");
+ char *l = freadline(stdin, &hist);
+ if (l == NULL) break;
+
+ if (!strcmp(l, "exit")) {
+ free(l);
+ break;
+ }
+
+ prog_ip = l;
+ get_token();
+ if (token_type == NUMBER) { // label. insert line.
+ insert_line(l, atoi(token));
+ } else { // directly execute
+ start(l);
+ }
+ free(l);
+ }
+ } else {
+ printf("usage:\n\t%s <filename>\trun BASIC file\n", argv[0]);
+ printf("\n\t%s\t\t\tinteractive BASIC interpreter\n", argv[0]);
+ exit(1);
+ }
+
+ return 0;
+}
+
diff --git a/src/user/app/kbasic/pppg.bas b/src/user/app/kbasic/pppg.bas
new file mode 100644
index 0000000..32fc050
--- /dev/null
+++ b/src/user/app/kbasic/pppg.bas
@@ -0,0 +1,14 @@
+
+n = RND % 100
+e = 0
+
+20 input "Devinez le nombre: ", i
+e = e + 1
+if i > n then print "Trop grand !"
+if i < n then print "Trop petit !"
+if i = n then goto 42
+goto 20
+
+42 print "Bravo, vous avez trouvé en ", e, " essais!"
+end
+
diff --git a/src/user/app/kbasic/tables.bas b/src/user/app/kbasic/tables.bas
new file mode 100644
index 0000000..31e9ce3
--- /dev/null
+++ b/src/user/app/kbasic/tables.bas
@@ -0,0 +1,15 @@
+input "Taille de la table: ", k
+print "Table d'addition:"
+for i = 0 to k
+ for j = 0 to k
+ print i+j;
+ next
+ print
+next
+print "Table de multiplication:"
+for i = 1 to k
+ for j = 1 to k
+ print i * j;
+ next
+ print
+next
diff --git a/src/user/app/kbasic/var.c b/src/user/app/kbasic/var.c
new file mode 100644
index 0000000..a49ce61
--- /dev/null
+++ b/src/user/app/kbasic/var.c
@@ -0,0 +1,19 @@
+#include <ctype.h>
+
+#include "basic.h"
+
+int variables[26]= { /* 26 user variables, A-Z */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
+
+/* Find a pointer to the value of a variable. */
+int* find_var(char *s)
+{
+ if(!isalpha(*s)){
+ serror(4); /* not a variable */
+ return 0;
+ }
+ return variables + (toupper(*s)-'A');
+}
diff --git a/src/user/app/led/main.c b/src/user/app/led/main.c
index 5e73c59..dcf830d 100644
--- a/src/user/app/led/main.c
+++ b/src/user/app/led/main.c
@@ -33,7 +33,7 @@ void parse_range(char *k, int *l1, int *l2) {
}
}
-int main(char **args) {
+int main(int argc, char **args) {
int linecount;
char **lines;
int i, j;
@@ -53,7 +53,7 @@ int main(char **args) {
lines = malloc(1 * sizeof(char*));
lines[0] = 0;
} else if (info.type & FT_FILE) {
- FILE f = open(args[1], FM_READ);
+ int f = open(args[1], FM_READ);
char* buff = (char*)malloc(info.size);
read(f, 0, info.size, buff);
close(f);
@@ -95,7 +95,7 @@ int main(char **args) {
// run
while (lines) {
printf("[%d lines] ", linecount);
- char *s = freadline(term, &hist);
+ char *s = freadline(stdin, &hist);
if (strcmp(s, "q") == 0) {
break;
} else if (strcmp(s, "l") == 0) {
@@ -132,7 +132,7 @@ int main(char **args) {
}
// write buffer
- FILE f = open(args[1], FM_WRITE | FM_TRUNC | FM_CREATE | FT_FILE);
+ int f = open(args[1], FM_WRITE | FM_TRUNC | FM_CREATE | FT_FILE);
if (f > 0) {
write(f, 0, buffsz, buff);
close(f);
diff --git a/src/user/app/prime/main.c b/src/user/app/prime/main.c
index d3ebb7d..d9b60ab 100644
--- a/src/user/app/prime/main.c
+++ b/src/user/app/prime/main.c
@@ -8,7 +8,7 @@ int is_prime(int i) {
return 1;
}
-int main(char **args) {
+int main(int argc, char **args) {
int i;
for (i = 2; i < 1000000; i++) {
if (is_prime(i)) printf("%d\t", i);
diff --git a/src/user/app/test/main.c b/src/user/app/test/main.c
index 939a15a..3db24b3 100644
--- a/src/user/app/test/main.c
+++ b/src/user/app/test/main.c
@@ -39,7 +39,7 @@ void useless_thread(void* d) {
}
}
-int main(char** args) {
+int main(int argc, char** args) {
char**a;
if (args != 0) {
printk("(test) args");
diff --git a/src/user/app/yosh/Makefile b/src/user/app/yosh/Makefile
index bf55ce1..759531e 100644
--- a/src/user/app/yosh/Makefile
+++ b/src/user/app/yosh/Makefile
@@ -1,6 +1,6 @@
Obj = main.o
Out = yosh.elf
-include $(SrcPath)/user/app/fwik.make
+include $(SrcPath)/user/app/common.make
LDFLAGS += -Map yosh.map
diff --git a/src/user/app/yosh/main.c b/src/user/app/yosh/main.c
new file mode 100644
index 0000000..7c9b875
--- /dev/null
+++ b/src/user/app/yosh/main.c
@@ -0,0 +1,292 @@
+#include <tce/syscall.h>
+#include <tce/vfs.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <readline.h>
+
+char *cwd;
+
+void about() {
+ printf("Trivial/Computing Environment v0.1.4 - yosh 4.\n");
+}
+
+void help(char **args) {
+ if (!args[1]) {
+ printf("Available commands: about, help, exit, ls, cd, goto.\n");
+ } else if (!strcmp(args[1], "about")) {
+ printf("Usage:\tabout\nShows some info about yosh. Very usefull.\n");
+ } else if (!strcmp(args[1], "help")) {
+ printf("Usage:\thelp\n\thelp <command>\n");
+ printf("Shows some info about the command you want, or commands in general.\n");
+ } else if (!strcmp(args[1], "exit")) {
+ printf("Usage:\texit\n");
+ printf("Exits the shell.\nWill probably make your system panic if you only have a shell running.\n");
+ } else if (!strcmp(args[1], "cd")) {
+ printf("Usage:\tcd <location>\nGoes to the location specified.\n");
+ } else if (!strcmp(args[1], "ls")) {
+ printf("Usage:\tls\n\tls <location>...\nShows the content of the current/specified directory.\n");
+ } else if (!strcmp(args[1], "goto")) {
+ printf("Usage:\tgoto <vt name>\nSwitchs focus to specified virtual terminal.\n");
+ printf("Type `ls /.ui` to see available terminals.\n");
+ } else {
+ printf("No such command: %s\n", args[1]);
+ }
+}
+
+void cd(char **args) {
+ if (!args[1]) {
+ printf("Usage: cd <directory>\n");
+ }
+ if (!strcmp(args[1], ".")) return;
+
+ char* newcwd = path_cat(cwd, args[1], 1);
+
+ file_info f;
+ int r = stat(newcwd, &f);
+ if (r == E_NOT_FOUND) {
+ printf("No such file or directory.\n");
+ } else if (r != 0) {
+ printf("Error stating: %i\n", r);
+ } else if (!(f.type & FT_DIR)) {
+ printf("Not a directory.\n");
+ } else {
+ free(cwd);
+ cwd = newcwd;
+ return;
+ }
+ free(newcwd);
+}
+
+void ls_dir(int fd) {
+ char buf[256];
+ int pos = 0;
+
+ while (read(fd, pos++, 256, buf) > 0) {
+ if ((!strcmp(buf, ".")) || (!strcmp(buf, ".."))) continue;
+
+ printf(" %s", buf);
+
+ file_info info;
+ stat_relative(fd, buf, &info);
+ if (info.type & FT_DIR) printf("/");
+ printf(" \t");
+
+ if (info.type & FT_FILE) printf("file ");
+ if (info.type & FT_DIR) printf("dir ");
+ if (info.type & FT_SYMLINK) printf("symlink ");
+ if (info.type & FT_DEV) printf("dev ");
+ if (info.type & FT_TERMINAL) printf("term ");
+
+ printf("\t");
+ if (info.type & FT_TERMINAL) {
+ printf("%ix%i", info.size >> 16, info.size & 0xFFFF);
+ } else if ((info.type & FT_DEV) == 0) {
+ printf("%i", info.size);
+ }
+
+ printf("\n");
+ }
+}
+
+void ls(char **args) {
+ if (!args[1]) {
+ int fd = open(cwd, FM_READ);
+ if (fd > 0) {
+ ls_dir(fd);
+ close(fd);
+ } else {
+ printf(" Could not open for read (%d).\n", fd);
+ }
+ } else {
+ int i;
+ for (i = 1; args[i]; i++) {
+ printf("Contents of %s :\n", args[i]);
+ char *d = path_cat(cwd, args[i], 1);
+
+ file_info i;
+ int r = stat(d, &i);
+
+ if (r == E_NOT_FOUND) {
+ printf(" No such file or directory\n");
+ } else if (r != 0) {
+ printf(" Error stating: %i\n", r);
+ } else if (!(i.type & FT_DIR)) {
+ printf(" Not a directory.\n");
+ } else {
+ int fd = open(d, FM_READ);
+ if (fd > 0) {
+ ls_dir(fd);
+ close(fd);
+ } else {
+ printf(" Could not open for read (%d).\n", fd);
+ }
+ }
+ free(d);
+ }
+ }
+}
+
+void cat(char **args) {
+ int i;
+ for (i = 1; args[i]; i++) {
+ char *d = path_cat(cwd, args[i], 0);
+ file_info info;
+ int e = stat(d, &info);
+ if (e == E_NOT_FOUND) {
+ printf("No such file: %s\n", d);
+ } else if (e < 0) {
+ printf("Error stating %s : %i\n", d, e);
+ } else if ((info.type & FT_FILE) == 0) {
+ printf("Not a file: %s\n", d);
+ } else {
+ int ff = open(d, 0);
+ char* buff = (char*)malloc(info.size);
+ read(ff, 0, info.size, buff);
+ close(ff);
+ write(term.fd, 0, info.size, buff);
+ free(buff);
+ }
+ free(d);
+ }
+}
+
+void t_goto(char **args) {
+ if (!args[1]) {
+ printf("Usage: goto <vt_name>\n");
+ return;
+ }
+ char *p = path_cat("/.ui/", args[1], 0);
+ int i;
+ if ((i = link(p, "/.dev/vgatxt", LM_OUTPUT_TO)) == 0) {
+ link("/.dev/ps2kbd", p, LM_OUTPUT_TO);
+ } else {
+ printf("Error %i\n", i);
+ }
+ free(p);
+}
+
+int main(int argc, char **sh_args) {
+ about();
+
+ cwd = strdup("/");
+
+ char *path = path_cat(sh_args[0], "..", 1);
+
+ int bg_pr[128], bg_pr_c = 0;
+
+ readline_history hist;
+ hist.str = 0; hist.max = 10;
+
+ while (1) {
+ // check for background processes that may have finished
+ int p = 0;
+ while (p < bg_pr_c) {
+ int ret = waitpid(bg_pr[p], 0);
+ if (ret != E_NOT_FINISHED) {
+ printf("(yosh) child (pid %i) exited with status %i\n", bg_pr[p], ret);
+ bg_pr_c--;
+ bg_pr[p] = bg_pr[bg_pr_c];
+ } else {
+ p++;
+ }
+ }
+
+ // show prompt
+ printf("\x1b[33m %s \x1b[1m", cwd);
+ char *s = freadline(stdin, &hist);
+ printf("\x1b[0m");
+ if (s == NULL) break;
+ if (strlen(s) == 0) continue;
+
+ char *a_c = strdup(s); // duplicate because we're gonna add '\0'es
+
+ char *c_args[16];
+ char *start = a_c, *pos = a_c;
+ int argc = 0;
+ while (*pos) {
+ if (*pos == ' ') {
+ if (pos == start) {
+ start++;
+ } else {
+ *pos = 0;
+ c_args[argc] = start;
+ argc++;
+ start = pos + 1;
+ if (argc == 14) {
+ break;
+ }
+ }
+ }
+ pos++;
+ }
+ c_args[argc++] = start;
+ c_args[argc] = 0;
+
+ if (!strcmp(c_args[0], "about")) {
+ about();
+ } else if (!strcmp(c_args[0], "help")) {
+ help(c_args);
+ } else if (!strcmp(c_args[0], "exit")) {
+ printf("Exiting the shell. See you later!\n");
+ break;
+ } else if (!strcmp(c_args[0], "cd")) {
+ cd(c_args);
+ } else if (!strcmp(c_args[0], "ls")) {
+ ls(c_args);
+ } else if (!strcmp(c_args[0], "goto")) {
+ t_goto(c_args);
+ } else if (!strcmp(c_args[0], "cat")) {
+ cat(c_args);
+ } else {
+ char **first_arg = c_args;
+
+ char *term_s = NULL;
+ int vt_fd = term.fd;
+
+ if (!strcmp(c_args[0], "on")) {
+ if (!c_args[1] || !c_args[2]) {
+ printf("Usage:\ton <vt> <command>\n");
+ continue;
+ }
+ term_s = path_cat("/.ui/", c_args[1], 1);
+ vt_fd = open(term_s, 0);
+ if (vt_fd < 0 || vt_fd == term.fd) {
+ printf("Error: cannot open terminal %s (%i)\n", term_s, vt_fd);
+ continue;
+ }
+ first_arg += 2;
+ }
+
+ char *c;
+ if (strchr(*first_arg, '/')) {
+ c = path_cat(cwd, *first_arg, 0);
+ } else {
+ c = path_cat(path, *first_arg, 0);
+ }
+ first_arg++;
+
+ int pid = run(c, (const char**)first_arg, vt_fd);
+ if (pid <= 0) {
+ if (pid == E_NOT_FOUND) {
+ printf("Error: no such file %s\n", c);
+ } else {
+ printf("Error %i\n", pid);
+ }
+ } else {
+ if (term_s == NULL) {
+ int ret = waitpid(pid, 1);
+ printf("(yosh) child (pid %i) exited with status %i\n", pid, ret);
+ } else {
+ printf("(yosh) running on terminal %s, pid:%i\n", term_s, pid);
+ bg_pr[bg_pr_c++] = pid;
+ }
+ }
+ free(c);
+ if (term_s) free(term_s);
+ }
+
+ free(a_c);
+ }
+
+ return 0;
+}
diff --git a/src/user/app/yosh/main.cpp b/src/user/app/yosh/main.cpp
deleted file mode 100644
index 160e728..0000000
--- a/src/user/app/yosh/main.cpp
+++ /dev/null
@@ -1,271 +0,0 @@
-#include <tce/syscall.h>
-#include <tce/vfs.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <readline.h>
-#include <IO/IOStream.h>
-#include <IO/Dir.h>
-
-Dir *cwd_f;
-String cwd;
-
-void about() {
- stdio << "Trivial/Computing Environment v0.1.0 - yosh 3.\n";
-}
-
-void help(String *args) {
- if (!args[1]) {
- stdio << "Available commands: about, help, exit, ls, cd, goto.\n";
- } else if (args[1] == "about") {
- stdio << "Usage:\tabout\nShows some info about yosh. Very usefull.\n";
- } else if (args[1] == "help") {
- stdio << "Usage:\thelp\n\thelp <command>\n"
- << "Shows some info about the command you want, or commands in general.\n";
- } else if (args[1] == "exit") {
- stdio << "Usage:\texit\n"
- << "Exits the shell.\nWill probably make your system panic if you only have a shell running.\n";
- } else if (args[1] == "cd") {
- stdio << "Usage:\tcd <location>\nGoes to the location specified.\n";
- } else if (args[1] == "ls") {
- stdio << "Usage:\tls\n\tls <location>...\nShows the content of the current/specified directory.\n";
- } else if (args[1] == "goto") {
- stdio << "Usage:\tgoto <vt name>\nSwitchs focus to specified virtual terminal.\n"
- << "Type `ls /.ui` to see available terminals.\n";
- } else {
- stdio.printf("No such command: %s\n", args[1].c_str());
- }
-}
-
-void cd(String *args) {
- if (!args[1]) {
- stdio << "Usage: cd <directory>\n";
- }
- if (args[1] == ".") return;
-
- String newcwd = path_cat(cwd, args[1]);
-
- Dir *newdir = new Dir(newcwd.c_str(), 0);
- if (newdir->error == E_NOT_FOUND) {
- stdio << "No such file or directory.\n";
- } else if (newdir->error == E_INVALID_TYPE) {
- stdio << "Not a directory.\n";
- } else if (newdir->error != 0) {
- stdio.printf("Error stating: %i\n", newdir->error);
- } else {
- cwd_f->close();
- cwd = newcwd;
- cwd_f = newdir;
- }
-}
-
-void ls_dir(Dir *d) {
- if (d->error != 0) {
- return;
- }
- d->pos = 0;
- for (String name = d->read_ent(); name; name = d->read_ent()) {
- if (name == "." || name == "..") continue;
-
- stdio.printf(" %s", name.c_str());
-
- Node child(d->fd, name.c_str(), 0);
-
- if (child.info.type & FT_DIR) stdio << "/";
- stdio << " \t";
-
- if (child.info.type & FT_FILE) stdio << "file ";
- if (child.info.type & FT_DIR) stdio << "dir ";
- if (child.info.type & FT_SYMLINK) stdio << "symlink ";
- if (child.info.type & FT_DEV) stdio << "dev ";
- if (child.info.type & FT_TERMINAL) stdio << "term ";
-
- stdio << "\t";
- if (child.info.type & FT_TERMINAL) {
- stdio.printf("%ix%i", child.info.size >> 16, child.info.size & 0xFFFF);
- } else if ((child.info.type & FT_DEV) == 0) {
- stdio.printf("%i", child.info.size);
- }
-
- stdio << "\n";
- }
-}
-
-void ls(String *args) {
- if (!args[1]) {
- ls_dir(cwd_f);
- } else {
- int i;
- for (i = 1; args[i]; i++) {
- stdio.printf("Contents of %s :\n", args[i].c_str());
- String d = path_cat(cwd, args[i].c_str());
- Dir dir(d.c_str(), 0);
- if (dir.error == E_NOT_FOUND) {
- stdio << " No such file or directory\n";
- } else if (dir.error == E_INVALID_TYPE) {
- stdio.printf(" Not a directory.\n");
- } else if (dir.error < 0) {
- stdio.printf(" Error stating: %i\n", dir.error);
- } else {
- ls_dir(&dir);
- dir.close();
- }
- }
- }
-}
-
-void cat(String *args) {
- int i;
- for (i = 1; args[i]; i++) {
- String d = path_cat(cwd, args[i], false);
- file_info info;
- int e = libc::stat(d.c_str(), &info);
- if (e == E_NOT_FOUND) {
- stdio.printf("No such file: %s\n", d.c_str());
- } else if (e < 0) {
- stdio.printf("Error stating %s : %i\n", d.c_str(), e);
- } else if ((info.type & FT_FILE) == 0) {
- stdio.printf("Not a file: %s\n", d.c_str());
- } else {
- FILE ff = libc::open(d.c_str(), 0);
- char* buff = (char*)malloc(info.size);
- libc::read(ff, 0, info.size, buff);
- libc::close(ff);
- libc::write(stdio.term->fd, 0, info.size, buff);
- free(buff);
- }
- }
-}
-
-void t_goto(String *args) {
- if (!args[1]) {
- stdio << "Usage: goto <vt_name>\n";
- return;
- }
- String p = path_cat("/.ui/", args[1], false);
- int i;
- if ((i = libc::link(p.c_str(), "/.dev/vgatxt", LM_OUTPUT_TO)) == 0) {
- libc::link("/.dev/ps2kbd", p.c_str(), LM_OUTPUT_TO);
- } else {
- stdio.printf("Error %i\n", i);
- }
-}
-
-int Main(String *sh_args) {
- about();
-
- cwd = "/";
- cwd_f = new Dir("/", 0);
-
- String path = path_cat(sh_args[0], "..");
-
- int bg_pr[128], bg_pr_c = 0;
-
- Term *term = stdio.term;
- if (term == 0) {
- stdio << "Error: no terminal...\n";
- return -1;
- }
-
- while (1) {
- // check for background processes that may have finished
- int p = 0;
- while (p < bg_pr_c) {
- int ret = libc::waitpid(bg_pr[p], 0);
- if (ret != E_NOT_FINISHED) {
- stdio.printf("(yosh) child (pid %i) exited with status %i\n", bg_pr[p], ret);
- bg_pr_c--;
- bg_pr[p] = bg_pr[bg_pr_c];
- } else {
- p++;
- }
- }
-
- // show prompt
- stdio.printf("\x1b[33m %s \x1b[1m", cwd.c_str());
- String s = term->readline();
- stdio.printf("\x1b[0m");
- if (s.size() == 0) continue;
-
- String c_args[16];
- int argc = 0, start = 0;
- for (int i = 0; i < s.size(); i++) {
- if (s[i] == ' ') {
- if (start == i) {
- start++;
- } else {
- c_args[argc] = s.substr(start, i - start);
- argc++;
- start = i + 1;
- if (argc == 15) {
- break;
- }
- }
- }
- }
- c_args[argc++] = s.substr(start, s.size() - start);
-
- if (c_args[0] == "about") {
- about();
- } else if (c_args[0] == "help") {
- help(c_args);
- } else if (c_args[0] == "exit") {
- stdio << "Exiting the shell. See you later!\n";
- break;
- } else if (c_args[0] == "cd") {
- cd(c_args);
- } else if (c_args[0] == "ls") {
- ls(c_args);
- } else if (c_args[0] == "goto") {
- t_goto(c_args);
- } else if (c_args[0] == "cat") {
- cat(c_args);
- } else {
- FILE vt = term->fd;
- String *first_arg = c_args ;
- String t;
-
- if (c_args[0] == "on") {
- if (!c_args[1] || !c_args[2]) {
- stdio.printf("Usage:\ton <vt> <command>\n");
- continue;
- }
- t = path_cat("/.ui/", c_args[1], false);
- vt = libc::open(t.c_str(), 0);
- if (vt < 0 || vt == term->fd) {
- stdio.printf("Error: cannot open terminal %s (%i)\n", t.c_str(), vt);
- continue;
- }
- first_arg += 2;
- }
-
- String c;
- if (libc::strchr(first_arg->c_str(), '/')) {
- c = path_cat(cwd, *first_arg, false);
- } else {
- c = path_cat(path, *first_arg, false);
- }
- first_arg++;
- const char *run_args[15] = {0};
- for (int i = 0; first_arg[i]; i++) run_args[i] = first_arg[i].c_str();
-
- int pid = libc::run(c.c_str(), run_args, vt);
- if (pid <= 0) {
- if (pid == E_NOT_FOUND) {
- stdio.printf("Error: no such file %s\n", c.c_str());
- } else {
- stdio.printf("Error %i\n", pid);
- }
- } else {
- if (vt == term->fd) {
- int ret = libc::waitpid(pid, 1);
- stdio.printf("(yosh) child (pid %i) exited with status %i\n", pid, ret);
- } else {
- stdio.printf("(yosh) running on terminal %s, pid:%i\n", t.c_str(), pid);
- bg_pr[bg_pr_c++] = pid;
- }
- }
- }
- }
-
- return 0;
-}
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) {
diff --git a/src/user/link.ld b/src/user/link.ld
index aa3759c..9ab693d 100644
--- a/src/user/link.ld
+++ b/src/user/link.ld
@@ -1,4 +1,4 @@
-ENTRY (start)
+ENTRY (__tce_libc_start)
SECTIONS{
. = 0x100000;