summaryrefslogtreecommitdiff
path: root/src/user/knob
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/knob')
-rw-r--r--src/user/knob/block.c24
-rw-r--r--src/user/knob/env.c3
-rw-r--r--src/user/knob/file.c26
-rw-r--r--src/user/knob/format.c257
-rw-r--r--src/user/knob/heap.c32
-rw-r--r--src/user/knob/ipc.c45
-rw-r--r--src/user/knob/key.c67
-rw-r--r--src/user/knob/panic.c12
-rw-r--r--src/user/knob/task.c20
-rw-r--r--src/user/knob/user.c299
10 files changed, 387 insertions, 398 deletions
diff --git a/src/user/knob/block.c b/src/user/knob/block.c
index 94bd073..90f79e3 100644
--- a/src/user/knob/block.c
+++ b/src/user/knob/block.c
@@ -33,4 +33,28 @@ char *strdup(const char *from) {
char *buf = get_block(end - from);
blockcpy(buf, from, end - from);
return buf;
+}
+
+__attribute__ ((pure))
+bool strequ(const char *a, const char *b) {
+ while (true) {
+ if ((*a == '\0') != (*b == '\0'))
+ return false;
+ if (*a == '\0')
+ return true;
+ if (*a != *b)
+ return false;
+ ++a;
+ ++b;
+ }
+}
+
+__attribute__ ((pure))
+uint32_t strlen(const char *str) {
+ uint32_t len = 0;
+ while (*str) {
+ ++len;
+ ++str;
+ }
+ return len;
} \ No newline at end of file
diff --git a/src/user/knob/env.c b/src/user/knob/env.c
deleted file mode 100644
index 952ab86..0000000
--- a/src/user/knob/env.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#include <stdint.h>
-
-uint32_t current_drive; \ No newline at end of file
diff --git a/src/user/knob/file.c b/src/user/knob/file.c
index f1a039d..3083503 100644
--- a/src/user/knob/file.c
+++ b/src/user/knob/file.c
@@ -1,8 +1,9 @@
-#include <pland/syscall.h>
-#include <pland/pcrt.h>
#include <knob/format.h>
+#include <knob/panic.h>
#include <knob/heap.h>
-#include <knob/env.h>
+
+#include <pland/syscall.h>
+#include <pland/pcrt.h>
struct ofl_node {
struct ofl_node *next;
@@ -27,23 +28,10 @@ struct file {
};
const char *remove_prefix(const char *path, uint8_t *dn_out) {
- if ((path[0] != 's') || (path[1] != 'd'))
- goto no_prefix;
-
- const char *num_part = path + 2;
- for (uint32_t i = 0; num_part[i]; ++i)
- if (num_part[i] == ':') {
-
- uint32_t dn_large;
- if (!try_sntoi(num_part, i, &dn_large) || dn_large > 255)
- goto no_prefix;
-
- *dn_out = (uint8_t)dn_large;
- return num_part + i + 1;
- }
+ if ((path[0] == 's') && (path[1] == 'd'))
+ PANIC("remove_prefix not fully implemented");
-no_prefix:
- *dn_out = current_drive;
+ *dn_out = 0;//change this later to an "active drive" or something
return path;
}
diff --git a/src/user/knob/format.c b/src/user/knob/format.c
index 593b20c..54d50ef 100644
--- a/src/user/knob/format.c
+++ b/src/user/knob/format.c
@@ -1,48 +1,231 @@
-#include <stdbool.h>
-#include <stdint.h>
-
-bool try_sntoi(const char *s, uint32_t n, uint32_t *out) {
- uint32_t calc = 0;
- for (uint32_t i = 0; i < n; ++i) {
- if ((s[i] < '0') || (s[i] > '9'))
- return false;
- calc = calc * 10 + s[i] - '0';
- }
- *out = calc;
- return true;
-}
+#include <knob/block.h>
+#include <knob/panic.h>
+#include <knob/heap.h>
+
+#include <pland/syscall.h>
+#include <pland/pcrt.h>
+
+#include <stdarg.h>
+
+#define FORMAT_BUF_INIT_SIZE 200
+#define FORMAT_BUF_CHUNK_SIZE 50
-__attribute__ ((access (write_only, 2)))
-void itosz(uint32_t i, char *out) {
- if (!i) {
- *(uint16_t *)out = (uint16_t)'0';
+#define BAD_SPEC "%%UNKNOWN FORMAT SPEC%%"
+#define BAD_SPEC_LEN 23
+
+static char *buf;
+static uint32_t buf_s;
+static char *buf_i;
+
+static const char *const hextab = "0123456789abcdef";
+
+static void ensure(uint32_t extra) {
+ const uint32_t total_len = buf_i - buf + extra;
+ if (total_len < buf_s)
return;
+
+ buf_s = (total_len / FORMAT_BUF_CHUNK_SIZE + 1) * FORMAT_BUF_CHUNK_SIZE;
+
+ char *const new_buf = get_block(buf_s);
+ if (!new_buf)
+ PANIC("out of memory in knob format");
+ blockcpy(new_buf, buf, buf_i - buf);
+ free_block(buf);
+ buf_i += new_buf - buf;
+ buf = new_buf;
+}
+
+struct format_spec {
+ uint32_t len;
+ enum {
+ UNKNOWN,
+ CHAR,
+ STRING,
+ UNSIGNED_DECIMAL,
+ HEXADECIMAL
+ //TODO: signed decimal
+ } kind;
+};
+
+static const char *get_format(const char *from, struct format_spec *format_out) {
+ if (*from == 'n') {
+ ++from;
+ format_out->len = -1;
}
- bool zero = false;
- for (uint32_t m = 1000000000; m; m /= 10) {
- uint8_t d = (i / m) % 10;
- if (zero)
- *(out++) = d + '0';
- else if (d) {
- zero = true;
- *(out++) = d + '0';
+ else {
+ uint32_t len = 0;
+ while ((*from >= '0') && (*from <= '9'))
+ len = len * 10 + *(from++) - '0';
+ format_out->len = len;
+ }
+
+ switch (*from) {
+ case 'c':
+ format_out->kind = CHAR;
+ break;
+ case 's':
+ format_out->kind = STRING;
+ break;
+ case 'u':
+ format_out->kind = UNSIGNED_DECIMAL;
+ break;
+ case 'h':
+ case 'x':
+ format_out->kind = HEXADECIMAL;
+ break;
+ default:
+ format_out->kind = UNKNOWN;
+ break;
+ }
+
+ return from + 1;
+}
+
+//allocates new memory
+char *format_v(const char *fmt, va_list args) {
+ buf = get_block(FORMAT_BUF_INIT_SIZE);
+ if (!buf)
+ PANIC("out of memory in knob format");
+ buf_s = FORMAT_BUF_INIT_SIZE;
+ buf_i = buf;
+
+ while (*fmt) {
+ if (*fmt != '%') {
+ ensure(1);
+ *(buf_i++) = *(fmt++);
+ }
+ else if (fmt[1] == '%') {
+ ensure(1);
+ *(buf_i++) = '%';
+ fmt += 2;
+ }
+ else {
+ struct format_spec form;
+ fmt = get_format(fmt + 1, &form);
+ if (form.len == -1)
+ //should passing zero still have the special meaning?
+ form.len = va_arg(args, uint32_t);
+ switch (form.kind) {
+ case UNKNOWN:
+ ensure(BAD_SPEC_LEN);
+ blockcpy(buf_i, BAD_SPEC, BAD_SPEC_LEN);
+ buf_i += BAD_SPEC_LEN;
+ continue;
+
+ uint32_t ch;
+ case CHAR:
+ ch = va_arg(args, uint32_t);
+ ensure(1);
+ *(buf_i++) = (char)ch;
+ continue;
+
+ const char *str;
+ case STRING:
+ str = va_arg(args, const char *);
+ if (!form.len)
+ form.len = strlen(str);
+ ensure(form.len);
+ blockcpy(buf_i, str, form.len);
+ buf_i += form.len;
+ continue;
+
+ uint32_t k;
+ case UNSIGNED_DECIMAL:
+ k = va_arg(args, uint32_t);
+ if (!form.len) {
+ uint32_t n = 10;
+ ++form.len;
+ while (k >= n) {
+ ++form.len;
+ n *= 10;
+ }
+ }
+ ensure(form.len);
+ const uint32_t len_backup = form.len;
+ while (form.len--) {
+ buf_i[form.len] = (k % 10) + '0';
+ k /= 10;
+ }
+ buf_i += len_backup;
+ continue;
+
+ case HEXADECIMAL:
+ k = va_arg(args, uint32_t);
+ if (!form.len)
+ form.len = 8;
+ ensure(form.len);
+ const uint32_t hlen_backup = form.len;
+ while (form.len--) {
+ buf_i[form.len] = hextab[k % 16];
+ k >>= 4;
+ }
+ buf_i += hlen_backup;
+ continue;
+ }
}
}
- *out = '\0';
+
+ *buf_i = '\0';
+ return buf;
+}
+
+//allocates new memory
+char *format(const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ char *const res = format_v(fmt, args);
+ va_end(args);
+ return res;
+}
+
+void syslogf_v(const char *fmt, va_list args) {
+ char *const msg = format_v(fmt, args);
+ _system_log(msg);
+ free_block(msg);
}
-const char *const hex_digits = "0123456789abcdef";
+void syslogf(const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ syslogf_v(fmt, args);
+ va_end(args);
+}
-__attribute__ ((access (write_only, 2)))
-void itosz_h8(uint8_t i, char *out) {
- out[0] = hex_digits[i >> 4];
- out[1] = hex_digits[i & 0xf];
- out[2] = '\0';
+//reads a unsigned decimal terminated by either null or whitespace
+//returns length of string plus length of whitespace
+//returns 0 on failure
+uint32_t try_swtou(const char *from, uint32_t *i_out) {
+ const char *const old_from = from;
+ uint32_t v = 0;
+ while (*from && (*from != '\n') && (*from != ' ')) {
+ if ((*from < '0') || (*from > '9'))
+ return 0;
+ v = v * 10 + *(from++) - '0';
+ }
+ *i_out = v;
+ while ((*from == '\n') || (*from == ' '))
+ ++from;
+ return from - old_from;
}
-__attribute__ ((access (write_only, 2)))
-void itosz_h32(uint32_t i, char *out) {
- for (uint8_t digit = 0; digit < 8; ++digit)
- out[digit] = hex_digits[(i >> (28 - digit * 4)) & 0xf];
- out[8] = '\0';
+//reads a hexadecimal terminated by either null or whitespace
+//returns length of string plus length of whitespace
+//returns 0 on failure
+uint32_t try_swtoh(const char *from, uint32_t *i_out) {
+ const char *const old_from = from;
+ uint32_t v = 0;
+ while (*from && (*from != '\n') && (*from != ' ')) {
+ if ((*from >= '0') && (*from <= '9'))
+ v = v * 16 + *(from++) - '0';
+ else if ((*from >= 'a') && (*from <= 'f'))
+ v = v * 16 + *(from++) - 'a' + 10;
+ else if ((*from >= 'A') && (*from <= 'F'))
+ v = v * 16 + *(from++) - 'A' + 10;
+ else
+ return 0;
+ }
+ *i_out = v;
+ while ((*from == '\n') || (*from == ' '))
+ ++from;
+ return from - old_from;
} \ No newline at end of file
diff --git a/src/user/knob/heap.c b/src/user/knob/heap.c
index 49f9339..b770542 100644
--- a/src/user/knob/heap.c
+++ b/src/user/knob/heap.c
@@ -1,4 +1,7 @@
+#include <knob/format.h>
+
#include <pland/syscall.h>
+
#include <stdbool.h>
#include <stdint.h>
@@ -24,23 +27,8 @@ static void add_header(struct block_header *bh) {
__attribute__ ((malloc))
void *get_block(uint32_t bytes) {
-//char nbuf[11];
-//tell_user_sz("[heap::get_block]\n first_block = 0x");
-//itosz_h32((uint32_t)first_block, nbuf);
-//tell_user_sz(nbuf);
-//tell_user_sz("\n");
struct block_header *header = 0;
-
for (struct block_header *ptr = first_block; ptr; ptr = ptr->next) {
- //tell_user_sz(" ptr = 0x");
- //itosz_h32((uint32_t)ptr, nbuf);
- //tell_user_sz(nbuf);
- //tell_user_sz("\n &ptr->allocated = 0x");
- //itosz_h32((uint32_t)&ptr->allocated, nbuf);
- //tell_user_sz(nbuf);
- //tell_user_sz("\n ptr->allocated = ");
- //tell_user_sz(ptr->allocated ? "true\n" : "false\n");
-
if (ptr->allocated)
continue;
if (ptr->length == bytes) {
@@ -63,14 +51,7 @@ void *get_block(uint32_t bytes) {
if (!header) {
uint32_t size_with_header = bytes + sizeof(struct block_header);
if (!(size_with_header % 4096)) {
- //tell_user_sz(" allocate ");
- //itosz(size_with_header / 4096, nbuf);
- //tell_user_sz(nbuf);
- //tell_user_sz(" pages = 0x");
header = _allocate_ram(size_with_header / 4096);
- //itosz_h32((uint32_t)header, nbuf);
- //tell_user_sz(nbuf);
- //tell_user_sz("\n");
if (!header)
return 0;
header->length = bytes;
@@ -78,14 +59,7 @@ void *get_block(uint32_t bytes) {
}
else {
uint32_t pages = (bytes + sizeof(struct block_header) * 2) / 4096 + 1;
- //tell_user_sz(" allocate ");
- //itosz(pages, nbuf);
- //tell_user_sz(nbuf);
- //tell_user_sz(" pages = 0x");
header = _allocate_ram(pages);
- //itosz_h32((uint32_t)header, nbuf);
- //tell_user_sz(nbuf);
- //tell_user_sz("\n");
if (!header)
return 0;
header->length = bytes;
diff --git a/src/user/knob/ipc.c b/src/user/knob/ipc.c
new file mode 100644
index 0000000..dbf1a22
--- /dev/null
+++ b/src/user/knob/ipc.c
@@ -0,0 +1,45 @@
+#include <pland/syscall.h>
+
+//blocking, returns early if other process is dead.
+//return value is number of bytes written.
+uint32_t try_send_ipc(_task_handle_t to, void *buffer, uint32_t size) {
+ const uint32_t size_backup = size;
+ while (size) {
+ uint32_t res = _ipc_send(to, size, buffer);
+ if (!res) {
+ _wait_ipc_read(to);
+ _yield_task();
+ }
+ else if (res == -1)
+ return size_backup - size;
+ else {
+ size -= res;
+ buffer += res;
+ }
+ }
+}
+
+//blocking, returns early if other process is dead.
+//return value is number of bytes read.
+uint32_t read_ipc(_task_handle_t from, void *buffer, uint32_t size) {
+ const uint32_t size_backup = size;
+ while (size) {
+ uint32_t res = _ipc_read(from, size, buffer);
+ if (!res) {
+ _wait_ipc_send(from);
+ _yield_task();
+ }
+ else if (res == -1)
+ return size_backup - size;
+ else {
+ size -= res;
+ buffer += res;
+ }
+ }
+}
+
+void flush_ipc(_task_handle_t from) {
+ uint8_t buf[4096];
+ while (_ipc_read(from, 4096, buf))
+ ;
+} \ No newline at end of file
diff --git a/src/user/knob/key.c b/src/user/knob/key.c
new file mode 100644
index 0000000..1506f3b
--- /dev/null
+++ b/src/user/knob/key.c
@@ -0,0 +1,67 @@
+#include <keypack.h>
+
+static const char no_mod[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t','\n', 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, 0, '\'', 0, 0, 0, 0, ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 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, 0, 0, 0, 0, 0, '[','\\', ']', 0, 0,
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0
+};
+
+static const char shifted[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t','\n', 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '{', '|', '}', 0, 0,
+ '~', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0, 0, 0, 0, 0
+};
+
+static const char caps[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t','\n', 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, 0, '\'', 0, 0, 0, 0, ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 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, 0, 0, 0, 0, 0, '[','\\', ']', 0, 0,
+ '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0, 0, 0, 0, 0
+};
+
+static const char sh_caps[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t','\n', 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '{', '|', '}', 0, 0,
+ '~', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0
+};
+
+static const char num[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '+', '\n', '-', '.', '/'
+};
+
+__attribute__ ((pure))
+char key_to_char(struct key_packet kp) {
+ if (kp.key_id < 0x80) {
+ const char ch = (kp.modifiers & SHIFTS
+ ? kp.modifiers & CAPS
+ ? sh_caps : shifted
+ : kp.modifiers & CAPS
+ ? caps : no_mod)[kp.key_id];
+ return ch ? kp.modifiers & ALTS ? 0x80 & ch : ch : 0;
+ }
+
+ else if ((kp.modifiers & NUM) && ((kp.key_id & 0xf0) == 0xb0))
+ return num[kp.key_id & 0x0f];
+
+ else
+ return 0;
+} \ No newline at end of file
diff --git a/src/user/knob/panic.c b/src/user/knob/panic.c
new file mode 100644
index 0000000..1ff663c
--- /dev/null
+++ b/src/user/knob/panic.c
@@ -0,0 +1,12 @@
+#include <knob/format.h>
+
+#include <pland/syscall.h>
+#include <pland/pcrt.h>
+
+#include <stdint.h>
+
+__attribute__ ((noreturn))
+void panic(const char *filename, uint32_t line, const char *message) {
+ _system_log(format("panic in %s on line %u: %s", filename, line, message));
+ __pcrt_quit();
+} \ No newline at end of file
diff --git a/src/user/knob/task.c b/src/user/knob/task.c
index df5d38f..3bf3e85 100644
--- a/src/user/knob/task.c
+++ b/src/user/knob/task.c
@@ -4,7 +4,7 @@
#include <knob/heap.h>
#include <knob/block.h>
-_task_handle_t run_command(const char *path) {
+_task_handle_t run_command(const char *path, _task_handle_t stdio_task) {
uint8_t dn;
path = remove_prefix(path, &dn);
@@ -14,23 +14,21 @@ _task_handle_t run_command(const char *path) {
blockcpy(new_path, path, ptr - path);
new_path[ptr - path] = '\0';
- bool succeded = _start_task(dn, new_path, ptr + 1);
+ bool succeded = _start_task(dn, new_path, ptr + 1, stdio_task);
free_block(new_path);
return succeded;
}
- return _start_task(dn, path, "");
+ return _start_task(dn, path, "", stdio_task);
}
-bool try_run_command_blocking(const char *path) {
- _task_handle_t handle = run_command(path);
+bool try_run_command_blocking(const char *path, _task_handle_t stdio_task) {
+ _task_handle_t handle = run_command(path, stdio_task);
if (!handle)
return false;
- _wait_for_task(handle);
- _yield_task();
+ while (_is_task_running(handle)) {
+ _wait_for_task(handle);
+ _yield_task();
+ }
return true;
-}
-
-void yield_task() {
- _yield_task();
} \ No newline at end of file
diff --git a/src/user/knob/user.c b/src/user/knob/user.c
deleted file mode 100644
index 1e273bb..0000000
--- a/src/user/knob/user.c
+++ /dev/null
@@ -1,299 +0,0 @@
-#include <pland/syscall.h>
-#include <knob/block.h>
-#include <knob/heap.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-static const uint8_t caps_and_shift[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x22,
- 0x28, 0x29, 0x2a, 0x2b, 0x3c, 0x5f, 0x3e, 0x3f,
- 0x29, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5e, 0x26,
- 0x2a, 0x28, 0x3a, 0x3a, 0x3c, 0x2d, 0x3e, 0x3f,
-
- 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
- 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
- 0x78, 0x79, 0x7a, 0x57, 0x7c, 0x7d, 0x5e, 0x5f,
- 0x7e, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
- 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
- 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
-
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static const uint8_t caps_no_shift[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
- 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-
- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
- 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
- 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
- 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
-
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static const uint8_t shifted[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x22,
- 0x28, 0x29, 0x2a, 0x2b, 0x3c, 0x5f, 0x3e, 0x3f,
- 0x29, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5e, 0x26,
- 0x2a, 0x28, 0x3a, 0x3a, 0x3c, 0x2d, 0x3e, 0x3f,
-
- 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
- 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
- 0x78, 0x79, 0x7a, 0x57, 0x7c, 0x7d, 0x5e, 0x5f,
- 0x7e, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
- 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00,
-
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-__attribute__ ((const))
-char key_to_char(_key_code_t key) {
- return
- key & _KEY_CAPS
- ? key & _KEY_SHIFT
- ? caps_and_shift[key & 0xff]
- : caps_no_shift[key & 0xff]
- : key & _KEY_SHIFT
- ? shifted[key & 0xff]
- : key & 0xff;
-}
-
-static char get_key_char() {
- _key_code_t key;
- while (!(key = _get_key()))
- _yield_task();
- return key_to_char(key);
-}
-
-void tell_user_sz(const char *sz) {
- _log_string(sz);
-}
-
-//return value and max_length don't include null terminator
-uint32_t ask_user_line_sz(char *sz, uint32_t max_length) {
- char log_buf[2];
- log_buf[1] = '\0';
-
- uint32_t i;
- for (i = 0; i != max_length; ++i) {
- char key;
- replace:
- key = get_key_char();
- if (!key)
- goto replace;
- if (key & 0x80)
- goto replace;//TODO
- if (key == '\b') {
- if (i) {
- --i;
- _log_string("\b");
- }
- goto replace;
- }
-
- log_buf[0] = key;
- _log_string(log_buf);
-
- if (key == '\n')
- break;
- sz[i] = key;
- }
-
- sz[i] = '\0';
- return i;
-}
-
-struct history_entry {
- struct history_entry *prev;
- struct history_entry *next;
- const char *contents;
-};
-
-struct history {
- struct history_entry *earliest_history_item;
- struct history_entry *latest_history_item;
- uint32_t max_entries;
- uint32_t cur_entries;
-};
-
-struct history *new_history(uint32_t max_entries) {
- struct history *new = get_block(sizeof(struct history));
- new->latest_history_item = 0;
- new->earliest_history_item = 0;
- new->max_entries = max_entries;
- new->cur_entries = 0;
- return new;
-}
-
-void del_history(struct history *hs) {
- free_block(hs);
- for (struct history_entry *he = hs->latest_history_item; he; he = he->prev) {
- free_block(he);
- free_block(he->contents);
- }
-}
-
-//return value and max_length don't include null terminator
-uint32_t ask_user_line_sz_with_history(char *sz, uint32_t max_length, struct history *hs) {
- char log_buf[2];
- log_buf[1] = '\0';
- struct history_entry *cur_he = 0;
-
- uint32_t i;
- for (i = 0; i != max_length; ++i) {
- char key;
- replace:
- key = get_key_char();
- if (!key)
- goto replace;
- if (key == (char)_KEY_UP) {
- struct history_entry *new_cur_he = cur_he ? cur_he->prev : hs->latest_history_item;
- if (new_cur_he) {
- cur_he = new_cur_he;
- for (uint32_t j = 0; j < i; ++j)
- _log_string("\b");
- i = strcpy(sz, cur_he->contents);
- _log_string(sz);
- }
- goto replace;
- }
- if (key == (char)_KEY_DOWN) {
- cur_he = cur_he ? cur_he->next : 0;
- for (uint32_t j = 0; j < i; ++j)
- _log_string("\b");
- if (cur_he) {
- i = strcpy(sz, cur_he->contents);
- _log_string(sz);
- }
- else
- i = 0;
- goto replace;
- }
- if (key & 0x80)
- goto replace;//TODO
- if (key == '\b') {
- if (i) {
- --i;
- _log_string("\b");
- }
- goto replace;
- }
-
- log_buf[0] = key;
- _log_string(log_buf);
-
- if (key == '\n')
- break;
- sz[i] = key;
- }
-
- sz[i] = '\0';
-
- struct history_entry *new_he = get_block(sizeof(struct history_entry));
- new_he->contents = strdup(sz);
-
- new_he->next = 0;
- if (hs->latest_history_item) {
- new_he->prev = hs->latest_history_item;
- hs->latest_history_item->next = new_he;
- }
- else
- new_he->prev = 0;
- hs->latest_history_item = new_he;
- if (!hs->earliest_history_item)
- hs->earliest_history_item = new_he;
- if (hs->max_entries == hs->cur_entries) {
- free_block(hs->earliest_history_item);
- free_block(hs->earliest_history_item->contents);
- hs->earliest_history_item->next->prev = 0;
- hs->earliest_history_item = hs->earliest_history_item->next;
- }
- else
- ++(hs->cur_entries);
-
- for (struct history_entry *check_he = hs->latest_history_item->prev; check_he; check_he = check_he->prev) {
- if (blockequ(check_he->contents, sz, i + 1)) {
- check_he->next->prev = check_he->prev;
- if (check_he->prev)
- check_he->prev->next = check_he->next;
- else
- hs->earliest_history_item = check_he->next;
- free_block(check_he);
- free_block(check_he->contents);
- }
- }
-
- return i;
-} \ No newline at end of file