all repos — mgba @ fa884d071ecaa3e05ff20b45a67bf9500dd3d6b6

mGBA Game Boy Advance Emulator

src/feature/editline/cli-el-backend.c (view raw)

  1/* Copyright (c) 2013-2014 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "cli-el-backend.h"
  7
  8#include <mgba/core/version.h>
  9
 10#include <signal.h>
 11
 12static struct CLIDebugger* _activeDebugger;
 13
 14static char* _prompt(EditLine* el) {
 15	UNUSED(el);
 16	return "> ";
 17}
 18
 19static void _breakIntoDefault(int signal) {
 20	UNUSED(signal);
 21	mDebuggerEnter(&_activeDebugger->d, DEBUGGER_ENTER_MANUAL, 0);
 22}
 23
 24static unsigned char _tabComplete(EditLine* elstate, int ch) {
 25	UNUSED(ch);
 26	const LineInfo* li = el_line(elstate);
 27	if (!li->buffer[0]) {
 28		return CC_ERROR;
 29	}
 30
 31	struct CLIDebuggerEditLineBackend* elbe;
 32	el_get(elstate, EL_CLIENTDATA, &elbe);
 33	// TODO: not always true
 34	if (CLIDebuggerTabComplete(elbe->d.p, li->buffer, true, li->cursor - li->buffer)) {
 35		return CC_REDISPLAY;
 36	}
 37	return CC_ERROR;
 38}
 39
 40ATTRIBUTE_FORMAT(printf, 2, 3)
 41void _CLIDebuggerEditLinePrintf(struct CLIDebuggerBackend* be, const char* fmt, ...) {
 42	UNUSED(be);
 43	va_list args;
 44	va_start(args, fmt);
 45	vprintf(fmt, args);
 46	va_end(args);
 47}
 48
 49void _CLIDebuggerEditLineInit(struct CLIDebuggerBackend* be) {
 50	struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
 51	// TODO: get argv[0]
 52	elbe->elstate = el_init(binaryName, stdin, stdout, stderr);
 53	el_set(elbe->elstate, EL_PROMPT, _prompt);
 54	el_set(elbe->elstate, EL_EDITOR, "emacs");
 55
 56	el_set(elbe->elstate, EL_CLIENTDATA, elbe);
 57	el_set(elbe->elstate, EL_ADDFN, "tab-complete", "Tab completion", _tabComplete);
 58	el_set(elbe->elstate, EL_BIND, "\t", "tab-complete", 0);
 59	elbe->histate = history_init();
 60	HistEvent ev;
 61	history(elbe->histate, &ev, H_SETSIZE, 200);
 62	el_set(elbe->elstate, EL_HIST, history, elbe->histate);
 63	_activeDebugger = be->p;
 64	signal(SIGINT, _breakIntoDefault);
 65}
 66
 67void _CLIDebuggerEditLineDeinit(struct CLIDebuggerBackend* be) {
 68	struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
 69	history_end(elbe->histate);
 70	el_end(elbe->elstate);
 71	free(elbe);
 72}
 73
 74const char* _CLIDebuggerEditLineReadLine(struct CLIDebuggerBackend* be, size_t* len) {
 75	struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
 76	int count;
 77	*len = 0;
 78	const char* line = el_gets(elbe->elstate, &count);
 79	if (line) {
 80		if (count > 1) {
 81			// Crop off newline
 82			*len = (size_t) count - 1;
 83		} else if (count == 1) {
 84			*len = 1;
 85		}
 86	}
 87	return line;
 88}
 89void _CLIDebuggerEditLineLineAppend(struct CLIDebuggerBackend* be, const char* line) {
 90	struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
 91	el_insertstr(elbe->elstate, line);
 92}
 93
 94const char* _CLIDebuggerEditLineHistoryLast(struct CLIDebuggerBackend* be, size_t* len) {
 95	struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
 96	HistEvent ev;
 97	if (history(elbe->histate, &ev, H_FIRST) < 0) {
 98		*len = 0;
 99		return NULL;
100	}
101	const char* newline = strchr(ev.str, '\n');
102	if (!newline) {
103		*len = strlen(ev.str);
104	} else {
105		*len = newline - ev.str;
106	}
107
108	return ev.str;
109}
110
111void _CLIDebuggerEditLineHistoryAppend(struct CLIDebuggerBackend* be, const char* line) {
112	struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
113	HistEvent ev;
114	history(elbe->histate, &ev, H_ENTER, line);
115}
116
117struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void) {
118	struct CLIDebuggerEditLineBackend* elbe = malloc(sizeof(*elbe));
119	elbe->d.printf = _CLIDebuggerEditLinePrintf;
120	elbe->d.init = _CLIDebuggerEditLineInit;
121	elbe->d.deinit = _CLIDebuggerEditLineDeinit;
122	elbe->d.readline = _CLIDebuggerEditLineReadLine;
123	elbe->d.lineAppend = _CLIDebuggerEditLineLineAppend;
124	elbe->d.historyLast = _CLIDebuggerEditLineHistoryLast;
125	elbe->d.historyAppend = _CLIDebuggerEditLineHistoryAppend;
126	return &elbe->d;
127}