diff options
Diffstat (limited to 'src/user/lib')
-rw-r--r-- | src/user/lib/Makefile | 2 | ||||
-rw-r--r-- | src/user/lib/include/readline.h | 16 | ||||
-rw-r--r-- | src/user/lib/include/stdio.h | 4 | ||||
-rw-r--r-- | src/user/lib/include/tce/syscall.h | 4 | ||||
-rw-r--r-- | src/user/lib/std/readline.c | 139 | ||||
-rw-r--r-- | src/user/lib/std/stdio.c | 124 | ||||
-rw-r--r-- | src/user/lib/tce/syscall.c | 8 |
7 files changed, 222 insertions, 75 deletions
diff --git a/src/user/lib/Makefile b/src/user/lib/Makefile index 9111ff5..c2630c4 100644 --- a/src/user/lib/Makefile +++ b/src/user/lib/Makefile @@ -1,6 +1,6 @@ Out = _user.o Obj = tce/syscall.o std/_dlmalloc.o \ - std/stdio.o std/stdlib.o std/string.o std/sched.o \ + std/stdio.o std/stdlib.o std/string.o std/sched.o std/readline.o \ start.o include $(SrcPath)/common.make diff --git a/src/user/lib/include/readline.h b/src/user/lib/include/readline.h new file mode 100644 index 0000000..53193d7 --- /dev/null +++ b/src/user/lib/include/readline.h @@ -0,0 +1,16 @@ +#ifndef DEF_READLINE_H +#define DEF_READLINE_H + +#include <stdio.h> + +char* freadln(FILE f); // minimal line-reading function. user must free the returned value. + +typedef struct _rdln_hist { + int max; + int n; + char **str; +} readline_history; +char* readline(FILE f, readline_history *h); + +#endif + diff --git a/src/user/lib/include/stdio.h b/src/user/lib/include/stdio.h index 6c3a974..099746e 100644 --- a/src/user/lib/include/stdio.h +++ b/src/user/lib/include/stdio.h @@ -2,6 +2,7 @@ #define DEF_STDIO_H #include <stdarg.h> +#include <tce/syscall.h> extern FILE term; @@ -14,8 +15,7 @@ void fprint_int(FILE f, int number); void fprint_hex(FILE f, unsigned number); void fprintf(FILE f, char *s, ...); -void vsfprintf(FILE f, char *s, va_list arg); +void vfprintf(FILE f, char *s, va_list arg); -char* freadln(FILE f); #endif diff --git a/src/user/lib/include/tce/syscall.h b/src/user/lib/include/tce/syscall.h index 1811422..c182f40 100644 --- a/src/user/lib/include/tce/syscall.h +++ b/src/user/lib/include/tce/syscall.h @@ -19,8 +19,8 @@ int proc_priv(); void* sbrk(size_t size); void brk(void* ptr); -int run(char* file, char** args); -int waitpid(int pid); +int run(char* file, char** args, FILE zero_fd); +int waitpid(int pid, int block); FILE open(char* filename, int mode); FILE open_relative(FILE root, char* filename, int mode); diff --git a/src/user/lib/std/readline.c b/src/user/lib/std/readline.c new file mode 100644 index 0000000..a3beefa --- /dev/null +++ b/src/user/lib/std/readline.c @@ -0,0 +1,139 @@ +#include <readline.h> +#include <stdlib.h> + +char* freadln(FILE f) { + fprint(f, "\x1b[e"); // enable keyboard echo + int i; + + char *p = (char*)malloc(256); + char *b = p; + + while (1) { + int l = read(f, 0, 255, b); + if (l < 0) { + free(b); + return 0; + } + + for (i = 0; i < l; i++) { + if (b[i] == '\n') { + b[i+1] = 0; + return p; + } else if (b[i] == 27) { // ignore escape sequences + b[i] = 0; + l = i; + } + } + + int d = b - p + l; + + char* newp = (char*)malloc(d + 256); + memcpy(newp, p, d); + free(p); + p = newp; + b = p + d; + } +} + + +// ** READLINE + +char *readline(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*)); + for (i = 0; i < h->max; i++) h->str[i] = 0; + h->n = 0; + } + + int lid; + if (h->n < h->max) { + lid = h->n++; + } else { + free(h->str[0]); + int i; + for (i = 0; i < h->max - 1; i++) { + h->str[i] = h->str[i+1]; + } + lid = h->max - 1; + h->str[lid] = 0; + } + + if (h->str[lid] == 0) h->str[lid] = (char*)malloc(256); + + char *str = h->str[lid]; + str[0] = 0; + char *cur = str; // position in string + int len = 0; // string length + + while (1) { + int finished = 0; + + int te = cur - str; + + char buf[16]; + int l = read(f, 0, 16, buf); + if (l < 0) return 0; + + if (buf[0] == 27) { + if (buf[1] == '[') { + if (buf[2] == 'A') { // up + if (lid > 0) { + lid--; + str = h->str[lid]; + len = strlen(str); + cur = str + len; + } + } else if (buf[2] == 'B') { // down + if (lid < h->n - 1) { + lid++; + str = h->str[lid]; + len = strlen(str); + cur = str + len; + } + } else if (buf[2] == 'C') { // forward (right) + if (cur < str + len) cur++; + } else if (buf[2] == 'D') { // back (left) + if (cur > str) cur--; + } + } else { + // ALT sequence - ignore + } + } else if (buf[0] == '\n') { + finished = 1; + cur = str + len; + } else if (buf[0] == '\b') { + if (cur > str) { + cur--; + len--; + char* c; + for (c = cur; *c != 0; c++) c[0] = c[1]; + } + } else if (buf[0] == '\t') { + // ignore tabs -- todo: tab completion???? haha + } else if (buf[0] >= ' ') { + if (l < 255) { + char* c; + for (c = cur + len; c >= cur; c--) c[1] = c[0]; + cur[0] = buf[0]; + cur++; + len++; + } + } + + // ASSUMPTION : everything will fit on one line... + if (te > 0) fprintf(f, "\x1b[%iD", te); + fprintf(f, "\x1b[K%s", str); + te = len - (cur - str); + if (te > 0) fprintf(f, "\x1b[%iD", te); + + + if (finished) { + fprintf(f, "\n"); + if (h->str[h->n-1][0] == 0) h->n--; + return str; + } + } +} diff --git a/src/user/lib/std/stdio.c b/src/user/lib/std/stdio.c index 1628a78..b1778d6 100644 --- a/src/user/lib/std/stdio.c +++ b/src/user/lib/std/stdio.c @@ -7,7 +7,7 @@ void print(char *s) { fprint(term, s); } void printf(char *format, ...) { va_list ap; va_start(ap, format); - vsfprintf(term, format, ap); + vfprintf(term, format, ap); va_end(ap); } char* readln() { return freadln(term); } @@ -15,25 +15,22 @@ char* readln() { return freadln(term); } void fprintf(FILE f, char* format, ...) { va_list ap; va_start(ap, format); - vsfprintf(f, format, ap); + vfprintf(f, format, ap); va_end(ap); } +// INTERNAL, FOR FORMATTING -void fprint(FILE f, char *s) { - write(f, 0, strlen(s), s); -} - -void fprint_int(FILE f, int number) { +static char* format_int(char* buf, int number) { if (number == 0) { - fprint(f, "0"); - return; + *(buf++) = '0'; + return buf; } - int negative = 0; if (number < 0) { - negative = 1; + *(buf++) = '-'; number = 0 - number; } + int order = 0, temp = number, i; char numbers[] = "0123456789"; while (temp > 0) { @@ -41,86 +38,81 @@ void fprint_int(FILE f, int number) { temp /= 10; } - char s[32], *r; - if (negative) { - s[0] = '-'; - r = s + 1; - } else { - r = s; - } - for (i = order; i > 0; i--) { - r[i - 1] = numbers[number % 10]; + buf[i - 1] = numbers[number % 10]; number /= 10; } - r[order] = 0; - fprint(f, s); + return buf + order; } -void fprint_hex(FILE f, unsigned v) { - char s[11] = {'0', 'x', 0}; +static char* format_hex(char *buf, unsigned v) { + *(buf++) = '0'; + *(buf++) = 'x'; int i; - char hexdigits[] = "0123456789ABCDEF"; - for (i = 0; i < 8; i++) { - s[i + 2] = (hexdigits[v >> 28]); + *(buf++) = hexdigits[v >> 28]; v = v << 4; } - s[11] = 0; + return buf; +} + + +// FUNCTIONS + +void fprint(FILE f, char *s) { + write(f, 0, strlen(s), s); +} + +void fprint_int(FILE f, int number) { + char s[32]; + char *v = format_int(s, number); + *v = 0; + fprint(f, s); +} + +void fprint_hex(FILE f, unsigned v) { + char s[11]; + char *e = format_hex(s, v); + *e = 0; fprint(f, s); } -void vsfprintf(FILE f, char *format, va_list ap) { - char* start = format; +void vfprintf(FILE f, char *format, va_list ap) { + char bb[256]; + int bufl = 256; + + char *buf = bb; + char *end = buf; while (*format) { if (*format == '%') { - if (start != format) write(f, 0, format - start, start); + // ASSUMPTION : (TODO) WE HAVE ENOUGH SPACE - NOT THE CASE!!! format++; if (*format == 'd' || *format == 'i') { - fprint_int(f, va_arg(ap, int)); + end = format_int(end, va_arg(ap, int)); } else if (*format == 'p') { - fprint_hex(f, va_arg(ap, uint32_t)); + end = format_hex(end, va_arg(ap, uint32_t)); } else if (*format == 's') { - fprint(f, va_arg(ap, char*)); + char *s = va_arg(ap, char*); + strcpy(end, s); + end += strlen(s); } format++; - start = format; } else { - format++; + *(end++) = *(format++); } - } - if (start != format) write(f, 0, format - start, start); -} - -char* freadln(FILE f) { - int i; - - char *p = (char*)malloc(256); - char *b = p; - - while (1) { - int l = read(f, 0, 255, b); - if (l < 0) { - free(b); - return 0; + if (end - buf > bufl - 2) { + bufl *= 2; + char *nbuf = (char*)malloc(bufl); + memcpy(nbuf, buf, end - buf); + end = nbuf + (end - buf); + if (buf != bb) free(buf); + buf = nbuf; } - - for (i = 0; i < l; i++) { - if (b[i] == '\n') { - b[i+1] = 0; - return p; - } - } - - int d = b - p + l; - - char* newp = (char*)malloc(d + 256); - memcpy(newp, p, d); - free(p); - p = newp; - b = p + d; } + *end = 0; + fprint(f, buf); + if (buf != bb) free(buf); } diff --git a/src/user/lib/tce/syscall.c b/src/user/lib/tce/syscall.c index bc8bfd8..4304840 100644 --- a/src/user/lib/tce/syscall.c +++ b/src/user/lib/tce/syscall.c @@ -75,12 +75,12 @@ void brk(void* ptr) { // ********** proc -int run(char* filename, char** args) { - return call(SC_RUN, (unsigned)filename, (unsigned)args, 0, 0, 0); +int run(char* filename, char** args, FILE zero_fd) { + return call(SC_RUN, (unsigned)filename, (unsigned)args, (unsigned)zero_fd, 0, 0); } -int waitpid(int p) { - return call(SC_WAITPID, p, 0, 0, 0, 0); +int waitpid(int p, int block) { + return call(SC_WAITPID, p, block, 0, 0, 0); } // ********** file |