#include #include #include #include #include #include #include #include #include "interp.h" #include "runtime.h" static InterpResult RES; void tz_init(Tokenizer *tz, const char *str, size_t len) { tz->str = str; tz->len = len; tz->pos = 0; } void tz_free(Tokenizer *tz) { Token *tk = tz->tokens; while (tk) { Token *tmp = tk; tk = tk->next; dlfree(tmp); } } int tz_next(Tokenizer *tz, Token *out) { while (tz->pos < tz->len && string_chr_isspace(tz->str[tz->pos])) { tz->pos++; } if (tz->pos >= tz->len) { return 0; } size_t start = tz->pos; if (tz->str[start] == '"') { start++; do { tz->pos++; } while (tz->pos < tz->len && tz->str[tz->pos] != '"'); tz->pos++; out->ptr = tz->str + start; out->len = tz->pos - start - 1; } else { while (tz->pos < tz->len && !string_chr_isspace(tz->str[tz->pos])) { tz->pos++; } out->ptr = tz->str + start; out->len = tz->pos - start; } return 1; } void tz_classify(Tokenizer *tz) { Token *tk = tz->tokens; while (tk) { if (tk->ptr[0] == '"' && tk->ptr[tk->len - 1] == '"') { tk->type = TOK_STRING; } else { RtCmd *cmd = RTCMDS; while (cmd) { char tmpbuf[0xff] = {0}; usnprintf(tmpbuf, sizeof(tmpbuf), "%.*s", (int)tk->len, tk->ptr); if (string_strcmp(tmpbuf, cmd->cmdname) == 0) { tk->type = TOK_CMD; tk->cmd = cmd; break; } cmd = cmd->next; } } tk = tk->next; } } bool interp_readline(char *data, const char **bgptr, const char **endptr) { static char *nextstart; if (data) { nextstart = data; return true; } if (*nextstart == '\0') { return false; } *bgptr = nextstart; const char *scn = nextstart; for (;;) { while (*scn != '\0' && *scn != '\n') { scn++; } if (*scn == '\n') { if (scn > *bgptr && *(scn - 1) == '\\') { scn--; nextstart = scn; *nextstart = ' '; scn++; if (*scn == '\n') { scn++; } nextstart = scn; continue; } } break; } *endptr = scn - 1; while (string_chr_isspace(**bgptr) && *bgptr < *endptr) { (*bgptr)++; } while (string_chr_isspace(**endptr) && *endptr >= *bgptr) { (*endptr)--; } (*endptr)++; if (*scn == '\n') { scn++; } nextstart = scn; return true; } bool interp_runstring(const char *string, size_t len, InterpResult **res) { *res = &RES; rt_init(); bool ok = true; const char *bg, *end; interp_readline((char *)string, NULL, NULL); while (interp_readline(NULL, &bg, &end)) { size_t linelen = end - bg; Tokenizer tz = ZERO(&tz); tz_init(&tz, bg, linelen); Token toktmp = ZERO(&toktmp); while (tz_next(&tz, &toktmp)) { Token *tok = dlmalloc(sizeof(*tok)); tok->ptr = toktmp.ptr; tok->len = toktmp.len; LL_APPEND(tz.tokens, tok); } tz_classify(&tz); Token *cmdtk = tz.tokens; if (cmdtk->type != TOK_CMD) { ok = false; usprintf(RES.errmsg, "Expected cmd name, but got %.*s", (int)cmdtk->len, cmdtk->ptr); tz_free(&tz); goto done; } ok = cmdtk->cmd->fn(cmdtk->next); if (!ok) { ok = false; usprintf(RES.errmsg, "cmd %.*s failed", (int)cmdtk->len, cmdtk->ptr); tz_free(&tz); goto done; } tz_free(&tz); } done: return ok; }