<commit_before>/* Copyright (c) 2013-2014 <NAME>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cli-debugger.h"

#include "core/core.h"
#include "core/version.h"
#include "debugger/parser.h"
#include "util/string.h"

#include <signal.h>

#ifdef USE_PTHREADS
#include <pthread.h>
#endif

const char* ERROR_MISSING_ARGS = "Arguments missing"; // TODO: share
const char* ERROR_OVERFLOW = "Arguments overflow";

#ifndef NDEBUG
static void _breakInto(struct CLIDebugger*, struct CLIDebugVector*);
#endif
static void _continue(struct CLIDebugger*, struct CLIDebugVector*);
static void _disassemble(struct CLIDebugger*, struct CLIDebugVector*);
static void _next(struct CLIDebugger*, struct CLIDebugVector*);
static void _print(struct CLIDebugger*, struct CLIDebugVector*);
static void _printBin(struct CLIDebugger*, struct CLIDebugVector*);
static void _printHex(struct CLIDebugger*, struct CLIDebugVector*);
static void _printStatus(struct CLIDebugger*, struct CLIDebugVector*);
static void _printHelp(struct CLIDebugger*, struct CLIDebugVector*);
static void _quit(struct CLIDebugger*, struct CLIDebugVector*);
static void _readByte(struct CLIDebugger*, struct CLIDebugVector*);
static void _reset(struct CLIDebugger*, struct CLIDebugVector*);
static void _readHalfword(struct CLIDebugger*, struct CLIDebugVector*);
static void _readWord(struct CLIDebugger*, struct CLIDebugVector*);
static void _setBreakpoint(struct CLIDebugger*, struct CLIDebugVector*);
static void _clearBreakpoint(struct CLIDebugger*, struct CLIDebugVector*);
static void _setWatchpoint(struct CLIDebugger*, struct CLIDebugVector*);
static void _writeByte(struct CLIDebugger*, struct CLIDebugVector*);
static void _writeHalfword(struct CLIDebugger*, struct CLIDebugVector*);
static void _writeWord(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpByte(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpHalfword(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpWord(struct CLIDebugger*, struct CLIDebugVector*);

static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
	{ "b", _setBreakpoint, CLIDVParse, "Set a breakpoint" },
	{ "break", _setBreakpoint, CLIDVParse, "Set a breakpoint" },
	{ "c", _continue, 0, "Continue execution" },
	{ "continue", _continue, 0, "Continue execution" },
	{ "d", _clearBreakpoint, CLIDVParse, "Delete a breakpoint" },
	{ "delete", _clearBreakpoint, CLIDVParse, "Delete a breakpoint" },
	{ "dis", _disassemble, CLIDVParse, "Disassemble instructions" },
	{ "disasm", _disassemble, CLIDVParse, "Disassemble instructions" },
	{ "disassemble", _disassemble, CLIDVParse, "Disassemble instructions" },
	{ "h", _printHelp, CLIDVStringParse, "Print help" },
	{ "help", _printHelp, CLIDVStringParse, "Print help" },
	{ "i", _printStatus, 0, "Print the current status" },
	{ "info", _printStatus, 0, "Print the current status" },
	{ "n", _next, 0, "Execute next instruction" },
	{ "next", _next, 0, "Execute next instruction" },
	{ "p", _print, CLIDVParse, "Print a value" },
	{ "p/t", _printBin, CLIDVParse, "Print a value as binary" },
	{ "p/x", _printHex, CLIDVParse, "Print a value as hexadecimal" },
	{ "print", _print, CLIDVParse, "Print a value" },
	{ "print/t", _printBin, CLIDVParse, "Print a value as binary" },
	{ "print/x", _printHex, CLIDVParse, "Print a value as hexadecimal" },
	{ "q", _quit, 0, "Quit the emulator" },
	{ "quit", _quit, 0, "Quit the emulator" },
	{ "reset", _reset, 0, "Reset the emulation" },
	{ "r/1", _readByte, CLIDVParse, "Read a byte from a specified offset" },
	{ "r/2", _readHalfword, CLIDVParse, "Read a halfword from a specified offset" },
	{ "r/4", _readWord, CLIDVParse, "Read a word from a specified offset" },
	{ "status", _printStatus, 0, "Print the current status" },
	{ "w", _setWatchpoint, CLIDVParse, "Set a watchpoint" },
	{ "w/1", _writeByte, CLIDVParse, "Write a byte at a specified offset" },
	{ "w/2", _writeHalfword, CLIDVParse, "Write a halfword at a specified offset" },
	{ "w/4", _writeWord, CLIDVParse, "Write a word at a specified offset" },
	{ "watch", _setWatchpoint, CLIDVParse, "Set a watchpoint" },
	{ "x/1", _dumpByte, CLIDVParse, "Examine bytes at a specified offset" },
	{ "x/2", _dumpHalfword, CLIDVParse, "Examine halfwords at a specified offset" },
	{ "x/4", _dumpWord, CLIDVParse, "Examine words at a specified offset" },
#ifndef NDEBUG
	{ "!", _breakInto, 0, "Break into attached debugger (for developers)" },
#endif
	{ 0, 0, 0, 0 }
};

#ifndef NDEBUG
static void _handleDeath(int sig) {
	UNUSED(sig);
	printf("No debugger attached!\n");
}

static void _breakInto(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	UNUSED(debugger);
	UNUSED(dv);
	struct sigaction sa, osa;
	sa.sa_handler = _handleDeath;
	sigemptyset(&sa.sa_mask);
	sigaddset(&sa.sa_mask, SIGTRAP);
	sa.sa_flags = SA_RESTART;
	sigaction(SIGTRAP, &sa, &osa);
#ifdef USE_PTHREADS
	pthread_kill(pthread_self(), SIGTRAP);
#else
	kill(getpid(), SIGTRAP);
#endif
	sigaction(SIGTRAP, &osa, 0);
}
#endif

static void _continue(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	UNUSED(dv);
	debugger->d.state = DEBUGGER_RUNNING;
}

static void _next(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	UNUSED(dv);
	debugger->d.core->step(debugger->d.core);
	_printStatus(debugger, 0);
}

static void _disassemble(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	debugger->system->disassemble(debugger->system, dv);
}

static void _print(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	for (; dv; dv = dv->next) {
		debugger->backend->printf(debugger->backend, " %u", dv->intValue);
	}
	debugger->backend->printf(debugger->backend, "\n");
}

static void _printBin(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	for (; dv; dv = dv->next) {
		debugger->backend->printf(debugger->backend, " 0b");
		int i = 32;
		while (i--) {
			debugger->backend->printf(debugger->backend, "%u", (dv->intValue >> i) & 1);
		}
	}
	debugger->backend->printf(debugger->backend, "\n");
}

static void _printHex(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	for (; dv; dv = dv->next) {
		debugger->backend->printf(debugger->backend, " 0x%08X", dv->intValue);
	}
	debugger->backend->printf(debugger->backend, "\n");
}

static void _printHelp(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	UNUSED(dv);
	if (!dv) {
		debugger->backend->printf(debugger->backend, "Generic commands:");
		int i;
		for (i = 0; _debuggerCommands[i].name; ++i) {
			debugger->backend->printf(debugger->backend, "%-10s %s\n", _debuggerCommands[i].name, _debuggerCommands[i].summary);
		}
		if (debugger->system) {
			debugger->backend->printf(debugger->backend, "%s commands:\n", debugger->system->platformName);
			for (i = 0; debugger->system->platformCommands[i].name; ++i) {
				debugger->backend->printf(debugger->backend, "%-10s %s\n", debugger->system->platformCommands[i].name, debugger->system->platformCommands[i].summary);
			}
			debugger->backend->printf(debugger->backend, "%s commands:\n", debugger->system->name);
			for (i = 0; debugger->system->commands[i].name; ++i) {
				debugger->backend->printf(debugger->backend, "%-10s %s\n", debugger->system->commands[i].name, debugger->system->commands[i].summary);
			}
		}<commit_msg>Debugger: Fix missing newline<commit_after>/* Copyright (c) 2013-2014 <NAME>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cli-debugger.h"

#include "core/core.h"
#include "core/version.h"
#include "debugger/parser.h"
#include "util/string.h"

#include <signal.h>

#ifdef USE_PTHREADS
#include <pthread.h>
#endif

const char* ERROR_MISSING_ARGS = "Arguments missing"; // TODO: share
const char* ERROR_OVERFLOW = "Arguments overflow";

#ifndef NDEBUG
static void _breakInto(struct CLIDebugger*, struct CLIDebugVector*);
#endif
static void _continue(struct CLIDebugger*, struct CLIDebugVector*);
static void _disassemble(struct CLIDebugger*, struct CLIDebugVector*);
static void _next(struct CLIDebugger*, struct CLIDebugVector*);
static void _print(struct CLIDebugger*, struct CLIDebugVector*);
static void _printBin(struct CLIDebugger*, struct CLIDebugVector*);
static void _printHex(struct CLIDebugger*, struct CLIDebugVector*);
static void _printStatus(struct CLIDebugger*, struct CLIDebugVector*);
static void _printHelp(struct CLIDebugger*, struct CLIDebugVector*);
static void _quit(struct CLIDebugger*, struct CLIDebugVector*);
static void _readByte(struct CLIDebugger*, struct CLIDebugVector*);
static void _reset(struct CLIDebugger*, struct CLIDebugVector*);
static void _readHalfword(struct CLIDebugger*, struct CLIDebugVector*);
static void _readWord(struct CLIDebugger*, struct CLIDebugVector*);
static void _setBreakpoint(struct CLIDebugger*, struct CLIDebugVector*);
static void _clearBreakpoint(struct CLIDebugger*, struct CLIDebugVector*);
static void _setWatchpoint(struct CLIDebugger*, struct CLIDebugVector*);
static void _writeByte(struct CLIDebugger*, struct CLIDebugVector*);
static void _writeHalfword(struct CLIDebugger*, struct CLIDebugVector*);
static void _writeWord(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpByte(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpHalfword(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpWord(struct CLIDebugger*, struct CLIDebugVector*);

static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
	{ "b", _setBreakpoint, CLIDVParse, "Set a breakpoint" },
	{ "break", _setBreakpoint, CLIDVParse, "Set a breakpoint" },
	{ "c", _continue, 0, "Continue execution" },
	{ "continue", _continue, 0, "Continue execution" },
	{ "d", _clearBreakpoint, CLIDVParse, "Delete a breakpoint" },
	{ "delete", _clearBreakpoint, CLIDVParse, "Delete a breakpoint" },
	{ "dis", _disassemble, CLIDVParse, "Disassemble instructions" },
	{ "disasm", _disassemble, CLIDVParse, "Disassemble instructions" },
	{ "disassemble", _disassemble, CLIDVParse, "Disassemble instructions" },
	{ "h", _printHelp, CLIDVStringParse, "Print help" },
	{ "help", _printHelp, CLIDVStringParse, "Print help" },
	{ "i", _printStatus, 0, "Print the current status" },
	{ "info", _printStatus, 0, "Print the current status" },
	{ "n", _next, 0, "Execute next instruction" },
	{ "next", _next, 0, "Execute next instruction" },
	{ "p", _print, CLIDVParse, "Print a value" },
	{ "p/t", _printBin, CLIDVParse, "Print a value as binary" },
	{ "p/x", _printHex, CLIDVParse, "Print a value as hexadecimal" },
	{ "print", _print, CLIDVParse, "Print a value" },
	{ "print/t", _printBin, CLIDVParse, "Print a value as binary" },
	{ "print/x", _printHex, CLIDVParse, "Print a value as hexadecimal" },
	{ "q", _quit, 0, "Quit the emulator" },
	{ "quit", _quit, 0, "Quit the emulator" },
	{ "reset", _reset, 0, "Reset the emulation" },
	{ "r/1", _readByte, CLIDVParse, "Read a byte from a specified offset" },
	{ "r/2", _readHalfword, CLIDVParse, "Read a halfword from a specified offset" },
	{ "r/4", _readWord, CLIDVParse, "Read a word from a specified offset" },
	{ "status", _printStatus, 0, "Print the current status" },
	{ "w", _setWatchpoint, CLIDVParse, "Set a watchpoint" },
	{ "w/1", _writeByte, CLIDVParse, "Write a byte at a specified offset" },
	{ "w/2", _writeHalfword, CLIDVParse, "Write a halfword at a specified offset" },
	{ "w/4", _writeWord, CLIDVParse, "Write a word at a specified offset" },
	{ "watch", _setWatchpoint, CLIDVParse, "Set a watchpoint" },
	{ "x/1", _dumpByte, CLIDVParse, "Examine bytes at a specified offset" },
	{ "x/2", _dumpHalfword, CLIDVParse, "Examine halfwords at a specified offset" },
	{ "x/4", _dumpWord, CLIDVParse, "Examine words at a specified offset" },
#ifndef NDEBUG
	{ "!", _breakInto, 0, "Break into attached debugger (for developers)" },
#endif
	{ 0, 0, 0, 0 }
};

#ifndef NDEBUG
static void _handleDeath(int sig) {
	UNUSED(sig);
	printf("No debugger attached!\n");
}

static void _breakInto(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	UNUSED(debugger);
	UNUSED(dv);
	struct sigaction sa, osa;
	sa.sa_handler = _handleDeath;
	sigemptyset(&sa.sa_mask);
	sigaddset(&sa.sa_mask, SIGTRAP);
	sa.sa_flags = SA_RESTART;
	sigaction(SIGTRAP, &sa, &osa);
#ifdef USE_PTHREADS
	pthread_kill(pthread_self(), SIGTRAP);
#else
	kill(getpid(), SIGTRAP);
#endif
	sigaction(SIGTRAP, &osa, 0);
}
#endif

static void _continue(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	UNUSED(dv);
	debugger->d.state = DEBUGGER_RUNNING;
}

static void _next(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	UNUSED(dv);
	debugger->d.core->step(debugger->d.core);
	_printStatus(debugger, 0);
}

static void _disassemble(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	debugger->system->disassemble(debugger->system, dv);
}

static void _print(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	for (; dv; dv = dv->next) {
		debugger->backend->printf(debugger->backend, " %u", dv->intValue);
	}
	debugger->backend->printf(debugger->backend, "\n");
}

static void _printBin(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	for (; dv; dv = dv->next) {
		debugger->backend->printf(debugger->backend, " 0b");
		int i = 32;
		while (i--) {
			debugger->backend->printf(debugger->backend, "%u", (dv->intValue >> i) & 1);
		}
	}
	debugger->backend->printf(debugger->backend, "\n");
}

static void _printHex(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	for (; dv; dv = dv->next) {
		debugger->backend->printf(debugger->backend, " 0x%08X", dv->intValue);
	}
	debugger->backend->printf(debugger->backend, "\n");
}

static void _printHelp(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
	UNUSED(dv);
	if (!dv) {
		debugger->backend->printf(debugger->backend, "Generic commands:\n");
		int i;
		for (i = 0; _debuggerCommands[i].name; ++i) {
			debugger->backend->printf(debugger->backend, "%-10s %s\n", _debuggerCommands[i].name, _debuggerCommands[i].summary);
		}
		if (debugger->system) {
			debugger->backend->printf(debugger->backend, "%s commands:\n", debugger->system->platformName);
			for (i = 0; debugger->system->platformCommands[i].name; ++i) {
				debugger->backend->printf(debugger->backend, "%-10s %s\n", debugger->system->platformCommands[i].name, debugger->system->platformCommands[i].summary);
			}
			debugger->backend->printf(debugger->backend, "%s commands:\n", debugger->system->name);
			for (i = 0; debugger->system->commands[i].name; ++i) {
				debugger->backend->printf(debugger->backend, "%-10s %s\n", debugger->system->commands[i].name, debugger->system->commands[i].summary);
			}
		}
{'fraction_non_alphanumeric': 0.1500605082694635, 'fraction_numerical': 0.007260992335619202, 'mean_word_length': 5.758291685597456, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 151, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3487800', 'n_tokens_mistral': 5313, 'n_tokens_neox': 5284, 'n_words': 1355}