#include #include #include #include #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 ", 7)) source(space + 1); else if (blockequ(line, "set ", 4)) set(space + 1); else if (blockequ(line, "echo ", 5)) { tell_user_sz(space + 1); tell_user_sz("\n"); } else if (blockequ(line, "vars", 5)) dump_vars(); else if (blockequ(line, "quit", 5)) __pcrt_quit(); else if (blockequ(line, "clear", 6)) _clear_screen(); else if (blockequ(line, "help", 5)) 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" " clear clear the screen\n" " echo STRING print STRING\n" " set VAR VALUE set $VAR$ to VALUE\n" " vars dump variables\n" " quit exit highway\n" " help show this\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; } } }