#include #include #include #include "interp.h" #include "macros.h" #include "config.h" #define LINEBUF_MAX 1024 PID_t PID; Dev_t ps2kbdev; Config CONFIG; static Arg ARGS[] = { ARG("-m", ARG_STRING, &CONFIG.modestr), ARG("-f", ARG_STRING, &CONFIG.filepath), ARG("-logcmds", ARG_BOOL, &CONFIG.logcmds), ARG("-rs", ARG_STRING, &CONFIG.runstring), ARG_END(), }; void do_file(char *filepath); void set_config(void) { int32_t ret; if ((ret = parse_args(args(), argslen(), ARGS)) < 0) { uprintf("Could not parse args: %d\n", ret); } if (CONFIG.modestr != NULL) { if (string_strcmp(CONFIG.modestr, "interactive") == 0) { CONFIG.mode = MODE_INTERACTIVE; } else if (string_strcmp(CONFIG.modestr, "runfile") == 0) { CONFIG.mode = MODE_RUNFILE; } else if (string_strcmp(CONFIG.modestr, "runstring") == 0) { CONFIG.mode = MODE_RUNSTRING; } else { LOG(LOG_ERR, "Unknown mode %s\n", CONFIG.modestr); } } else { CONFIG.mode = MODE_RUNFILE; } } void do_file(char *filepath) { fsh_t h = fs_openf(filepath, FS_OF_READ); if (h < 0) { LOG(LOG_ERR, "Could not open %s: %s\n", filepath, ERRSTRING(h)); return; } FsStat statbuf; ZERO(&statbuf); fs_stat(filepath, &statbuf); if (statbuf.type != FSSTAT_FILE) { LOG(LOG_ERR, "%s is not a file (%d)\n", filepath, statbuf.type); return; } uint8_t *buf = umalloc(statbuf.size+1); string_memset(buf, 0, statbuf.size+1); if (fs_read(h, buf, statbuf.size, 0) < 0) { LOG(LOG_ERR, "Could not read %s (%d): %s\n", filepath, h, ERRSTRING(h)); goto done; } InterpResult *res; bool ok = interp_runstring((char *)buf, &res, CONFIG.mode == MODE_INTERACTIVE); if (!ok) { uprintf("Interpreter error:\n"); uprintf("%s\n", res->errmsg); goto done; } done: ufree(buf); fs_closef(h); } void do_mode_interactive(void) { char linebuf[LINEBUF_MAX]; size_t cursor; for(;;) { begin: uprintf("tb# "); cursor = 0; string_memset(linebuf, 0, LINEBUF_MAX); uint8_t b = 0; for (;;) { int32_t key = dev_cmd(&ps2kbdev, DEV_PS2KBDEV_READCH, NULL, 0); if (key > 0) { b = (uint8_t)key; switch (b) { case C('C'): case 0xE9: uprintf("\n"); goto begin; break; case C('L'): uprintf(ANSIQ_CUR_SET(0, 0)); uprintf(ANSIQ_SCR_CLR_ALL); goto begin; break; } if (b == '\n') { break; } if (string_chr_isascii(b) && b != 0 && cursor < LINEBUF_MAX) { linebuf[cursor++] = b; uprintf("%c", b); } } else { schedrelease(); } } if (cursor < LINEBUF_MAX) { linebuf[cursor] = '\0'; } uprintf(ANSIQ_GR_RESET); uprintf("\n"); InterpResult *res; if (!interp_runstring(linebuf, &res, CONFIG.mode == MODE_INTERACTIVE)) { LOG(LOG_ERR, "%s\n", res->errmsg); } } } void main(void) { PID = proc_getpid(); // short command-like script was supplied if (argslen() > 0 && args()[0][0] == '.') { do_file("base:/scripts/rc.tb"); char *path = umalloc(4096); usprintf(path, "base:/scripts/%s.tb", args()[1]); do_file(path); ufree(path); return; } set_config(); do_file("base:/scripts/rc.tb"); if (CONFIG.mode == MODE_INTERACTIVE) { dev_gethandle(&ps2kbdev, "ps2kbdev"); dev_cmd(&ps2kbdev, DEV_PS2KBDEV_ATTCHCONS, NULL, 0); do_mode_interactive(); } else if (CONFIG.mode == MODE_RUNFILE) { if (CONFIG.filepath == NULL) { uprintf("No file provided\n"); return; } do_file(CONFIG.filepath); } else if (CONFIG.mode == MODE_RUNSTRING) { if (CONFIG.runstring == NULL) { uprintf("Run string is empty\n"); return; } InterpResult *res; if (CONFIG.runstring[0] == '\'') { CONFIG.runstring[0] = ' '; } size_t len = string_len(CONFIG.runstring); if (CONFIG.runstring[len] == '\'') { CONFIG.runstring[len] = ' '; } if (!interp_runstring(CONFIG.runstring, &res, false)) { LOG(LOG_ERR, "%s\n", res->errmsg); } } }