#include #include #include #include #include #include #include "fuzzer.h" #include "text.h" #include "text-util.h" #include "util.h" #ifndef BUFSIZ #define BUFSIZ 1024 #endif typedef enum CmdStatus (*Cmd)(Text *txt, const char *cmd); static Mark mark = EMARK; static enum CmdStatus cmd_insert(Text *txt, const char *cmd) { char data[BUFSIZ]; size_t pos; if (sscanf(cmd, "%zu %s\n", &pos, data) != 2) return CMD_ERR; size_t len = strlen(data); return text_insert(txt, pos, data, len); } static enum CmdStatus cmd_delete(Text *txt, const char *cmd) { size_t pos, len; if (sscanf(cmd, "%zu %zu", &pos, &len) != 2) return CMD_ERR; return text_delete(txt, pos, len); } static enum CmdStatus cmd_size(Text *txt, const char *cmd) { printf("%zu bytes\n", text_size(txt)); return CMD_OK; } static enum CmdStatus cmd_snapshot(Text *txt, const char *cmd) { text_snapshot(txt); return CMD_OK; } static enum CmdStatus cmd_undo(Text *txt, const char *cmd) { return text_undo(txt) != EPOS; } static enum CmdStatus cmd_redo(Text *txt, const char *cmd) { return text_redo(txt) != EPOS; } static enum CmdStatus cmd_earlier(Text *txt, const char *cmd) { return text_earlier(txt, 1) != EPOS; } static enum CmdStatus cmd_later(Text *txt, const char *cmd) { return text_later(txt, 1) != EPOS; } static enum CmdStatus cmd_mark_set(Text *txt, const char *cmd) { size_t pos; if (sscanf(cmd, "%zu\n", &pos) != 1) return CMD_ERR; Mark m = text_mark_set(txt, pos); if (m != EMARK) mark = m; return m != EMARK; } static enum CmdStatus cmd_mark_get(Text *txt, const char *cmd) { size_t pos = text_mark_get(txt, mark); if (pos != EPOS) printf("%zu\n", pos); return pos != EPOS; } static enum CmdStatus cmd_print(Text *txt, const char *cmd) { size_t start = 0, size = text_size(txt), rem = size; for (Iterator it = text_iterator_get(txt, start); rem > 0 && text_iterator_valid(&it); text_iterator_next(&it)) { size_t prem = it.end - it.text; if (prem > rem) prem = rem; if (fwrite(it.text, prem, 1, stdout) != 1) return CMD_ERR; rem -= prem; } if (rem != size) puts(""); return rem == 0; } static enum CmdStatus cmd_quit(Text *txt, const char *cmd) { return CMD_QUIT; } static Cmd commands[] = { ['-'] = cmd_earlier, ['+'] = cmd_later, ['?'] = cmd_mark_get, ['='] = cmd_mark_set, ['#'] = cmd_size, ['d'] = cmd_delete, ['i'] = cmd_insert, ['p'] = cmd_print, ['q'] = cmd_quit, ['r'] = cmd_redo, ['s'] = cmd_snapshot, ['u'] = cmd_undo, }; int main(int argc, char *argv[]) { char line[BUFSIZ], *name = (argc == 1) ? NULL : argv[1]; Text *txt = text_load(name); if (!name) name = "-"; if (!txt) { fprintf(stderr, "Failed to load text from `%s'\n", name); return 1; } printf("Loaded %zu bytes from `%s'\n", text_size(txt), name); for (;;) { printf("> "); if (!fgets(line, sizeof(line), stdin)) break; if (!isatty(0)) printf("%s", line); if (line[0] == '\n') continue; size_t idx = line[0]; if (idx < LENGTH(commands) && commands[idx]) { enum CmdStatus ret = commands[idx](txt, line+1); printf("%s", cmd_status_msg[ret]); if (ret == CMD_QUIT) break; } else { puts("Invalid command"); } } text_free(txt); return 0; }