diff options
author | Alex AUVOLAT <alexis211@gmail.com> | 2013-06-08 23:09:52 +0200 |
---|---|---|
committer | Alex AUVOLAT <alexis211@gmail.com> | 2013-06-08 23:09:52 +0200 |
commit | 4d65fcb9a8b6c7c6fd5a3390c46a96d11b6a80d4 (patch) | |
tree | c193acf64ff2db985f6664f161cf586c3caeb684 | |
parent | eae9997d3c2dbaef53022ddabe61c1800a619499 (diff) | |
download | TCE-4d65fcb9a8b6c7c6fd5a3390c46a96d11b6a80d4.tar.gz TCE-4d65fcb9a8b6c7c6fd5a3390c46a96d11b6a80d4.zip |
All FWIK is deleted. YOSH is now pure C. Not-working KBASIC included.
61 files changed, 2116 insertions, 1049 deletions
@@ -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; |