This commit refactors the project using a single, consistent coding style, derived from the Linux Kernel Coding Style, available here: https://www.kernel.org/doc/Documentation/CodingStyle This includes, but is not limited to: * Removal of typedefs, especially for structs * Limiting lines to a reasonable length, 80 characters, mostly * K&R style braces * Removal of CamelCase
95 lines
2.6 KiB
C
95 lines
2.6 KiB
C
#include "tdb.h"
|
|
#include <tvm/tvm.h>
|
|
#include <tvm/tvm_parser.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#define TOKEN_LENGTH 32
|
|
#define MAX_TOKENS 3
|
|
#define MAX_INPUT_LENGTH 256
|
|
|
|
const char *commands[] = {"q", "run", "break", "step", "continue", 0};
|
|
|
|
static void tokenize(char *str, char **tokens);
|
|
static int cmd_to_idx(char *cmd);
|
|
|
|
void tdb_shell(struct tvm_ctx *vm)
|
|
{
|
|
int run = 1, i;
|
|
int running = 0;
|
|
|
|
char *tokens[MAX_TOKENS];
|
|
char str[MAX_INPUT_LENGTH];
|
|
|
|
int num_breakpoints = 0;
|
|
struct tdb_breakpoint *breakpoints = NULL;
|
|
|
|
for(i = 0; i < MAX_TOKENS; i++) tokens[i] = malloc(TOKEN_LENGTH);
|
|
|
|
vm->mem->registers[0x8].i32 = vm->prog->start;
|
|
|
|
while(run && !feof(stdin))
|
|
{
|
|
int retcode = 0;
|
|
|
|
printf(": ");
|
|
|
|
for(i = 0; i < MAX_TOKENS; i++) memset(tokens[i], 0, TOKEN_LENGTH);
|
|
|
|
if (!fgets(str, MAX_INPUT_LENGTH, stdin))
|
|
break;
|
|
tokenize(str, (char **)tokens);
|
|
|
|
switch(cmd_to_idx(tokens[0]))
|
|
{
|
|
case -0x1: printf("WARNING: \"%s\" is not a valid command.\n", tokens[0]); break;
|
|
case 0x0: run = 0; break;
|
|
case 0x1: if(running) printf("The program is already running.\n");
|
|
else { retcode = tdb_run(vm, breakpoints, num_breakpoints); running = 1; } break;
|
|
case 0x2: breakpoints = realloc(breakpoints, sizeof(struct tdb_breakpoint) * ++num_breakpoints);
|
|
breakpoints[num_breakpoints - 1].address = tvm_parse_value(tokens[1]); break;
|
|
case 0x3: tvm_step(vm, &vm->mem->registers[0x8].i32);
|
|
vm->mem->registers[0x8].i32++;
|
|
printf("Advancing instruction pointer to %i\n", vm->mem->registers[0x8].i32); break;
|
|
case 0x4: tvm_step(vm, &vm->mem->registers[0x8].i32);
|
|
vm->mem->registers[0x8].i32++;
|
|
retcode = tdb_run(vm, breakpoints, num_breakpoints); break;
|
|
};
|
|
|
|
if(vm->prog->instr[vm->mem->registers[0x8].i32] == -0x1) printf("End of program reached\n");
|
|
if(retcode == 1) printf("Breakpoint hit at address: %i\n", vm->mem->registers[0x8].i32);
|
|
}
|
|
|
|
free(breakpoints);
|
|
|
|
for(i = 0; i < MAX_TOKENS; i++) free(tokens[i]);
|
|
}
|
|
|
|
int tdb_run(struct tvm_ctx* vm, struct tdb_breakpoint* breakpoints, int num_breakpoints)
|
|
{
|
|
for(int *instr_idx = &vm->mem->registers[0x8].i32; vm->prog->instr[*instr_idx] != -0x1; ++(*instr_idx))
|
|
{
|
|
for(int i = 0; i < num_breakpoints; i++) if(breakpoints[i].address == *instr_idx) return 1; /* Breakpoint hit */
|
|
tvm_step(vm, instr_idx);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void tokenize(char *str, char **tokens)
|
|
{
|
|
char *token = strtok(str, " \n");
|
|
for(int i = 0; token && (i < MAX_TOKENS); i++)
|
|
{
|
|
strcpy(tokens[i], token);
|
|
token = strtok(NULL, " \n");
|
|
}
|
|
}
|
|
|
|
int cmd_to_idx(char* cmd)
|
|
{
|
|
for(int i = 0; commands[i]; i++)
|
|
if(strcmp(cmd, commands[i]) == 0) return i;
|
|
|
|
return -1;
|
|
}
|