diff options
Diffstat (limited to 'src/user/highway/line.c')
-rw-r--r-- | src/user/highway/line.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/user/highway/line.c b/src/user/highway/line.c new file mode 100644 index 0000000..ca38c9b --- /dev/null +++ b/src/user/highway/line.c @@ -0,0 +1,100 @@ +#include <knob/block.h> +#include <knob/quit.h> +#include <knob/task.h> +#include <knob/user.h> +#include "cmds.h" +#include "vars.h" + +#define LINE_SIZE 4096 +static char line[LINE_SIZE]; + +static void line_replace(const char *from) { + const char *fi = from; + char *ti = line; + while (*fi) { + if (ti == line + LINE_SIZE) { + tell_user_sz("Line too long.\n"); + line[0] = '\0'; + return; + } + if (*fi != '$') { + *ti = *fi; + ++ti; + ++fi; + continue; + } + const char *var_start = ++fi; + const char *var_end = var_start; + while (*var_end != '$') + if (!*var_end++) { + tell_user_sz("Unterminated variable name.\n"); + line[0] = '\0'; + return; + } + if (ti + (var_end - var_start) >= line + LINE_SIZE) { + tell_user_sz("Line too long.\n"); + line[0] = '\0'; + return; + } + struct no_null_sn vname = { + .data = var_start, + .length = var_end - var_start + }; + const struct no_null_sn *vval = get_var(vname); + if (!vval) + vval = &vname; + blockcpy(ti, vval->data, vval->length); + ti += vval->length; + fi = var_end + 1; + } + *ti = '\0'; +} + +void run_line(const char *original_line) { + line_replace(original_line); + if (!*line) + return; + const char *space; + for (space = line; *space && (*space != ' '); ++space) + ; + if (blockequ(line, "source", space - line)) + source(space + 1); + else if (blockequ(line, "set", space - line)) + set(space + 1); + else if (blockequ(line, "echo", space - line)) { + tell_user_sz(space + 1); + tell_user_sz("\n"); + } + else if (blockequ(line, "vars", space - line)) + dump_vars(); + else if (blockequ(line, "quit", space - line)) + quit(space + 1); + else if (blockequ(line, "help", space - line)) + tell_user_sz("Highway is a command shell for Portland OS. It includes variables and a couple\n" + "of pseudo-commands. Variables are addressed by surrounding with \"$\". The\n" + "following list shows each of the pseudo-commands.\n\n" + " source FILE run each command in FILE\n" + " set VAR VALUE set $VAR$ to VALUE\n" + " echo STRING print STRING\n" + " vars dump variables\n" + " quit exit highway\n" + " help show this\n\n"); + else if (!try_run_command_blocking(line)) { + struct no_null_sn arg = { + .data = "_path", + .length = 5 + }; + const struct no_null_sn *path = get_var(arg); + if (!path->length) { + tell_user_sz("Could not run command.\n"); + return; + } + for (uint16_t to_i = LINE_SIZE - 1; to_i >= path->length; --to_i) + line[to_i] = line[to_i - path->length]; + blockcpy(line, path->data, path->length); + if (!try_run_command_blocking(line)) { + tell_user_sz("Could not run command.\n"); + return; + } + } +}
\ No newline at end of file |