diff options
Diffstat (limited to 'src/user/knob')
-rw-r--r-- | src/user/knob/block.c | 24 | ||||
-rw-r--r-- | src/user/knob/env.c | 3 | ||||
-rw-r--r-- | src/user/knob/file.c | 26 | ||||
-rw-r--r-- | src/user/knob/format.c | 257 | ||||
-rw-r--r-- | src/user/knob/heap.c | 32 | ||||
-rw-r--r-- | src/user/knob/ipc.c | 45 | ||||
-rw-r--r-- | src/user/knob/key.c | 67 | ||||
-rw-r--r-- | src/user/knob/panic.c | 12 | ||||
-rw-r--r-- | src/user/knob/task.c | 20 | ||||
-rw-r--r-- | src/user/knob/user.c | 299 |
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 |