add: debug mode, (-d)
This commit is contained in:
9
Makefile
9
Makefile
@@ -2,7 +2,8 @@ SRC = src/pasm.c \
|
|||||||
src/file_utils.c \
|
src/file_utils.c \
|
||||||
src/interpreter_states.c \
|
src/interpreter_states.c \
|
||||||
src/instructions.c \
|
src/instructions.c \
|
||||||
src/api.c
|
src/api.c \
|
||||||
|
src/debug.c
|
||||||
OBJ = $(SRC:.c=.o)
|
OBJ = $(SRC:.c=.o)
|
||||||
NAME = pasm
|
NAME = pasm
|
||||||
CC = gcc
|
CC = gcc
|
||||||
@@ -23,10 +24,6 @@ $(NAME):
|
|||||||
|
|
||||||
interpreter: $(NAME)
|
interpreter: $(NAME)
|
||||||
|
|
||||||
debug: fclean
|
|
||||||
debug: CFLAGS += -DDEBUG -g3
|
|
||||||
debug: $(NAME)
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@-rm -f $(OBJ)
|
@-rm -f $(OBJ)
|
||||||
@-cd tests && $(MAKE) clean
|
@-cd tests && $(MAKE) clean
|
||||||
@@ -38,4 +35,4 @@ fclean: clean
|
|||||||
re: fclean
|
re: fclean
|
||||||
re: $(NAME)
|
re: $(NAME)
|
||||||
|
|
||||||
.PHONY : all $(NAME) clean fclean re interpreter lib debug
|
.PHONY : all $(NAME) clean fclean re interpreter lib
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// set to 1 for debug mode
|
||||||
|
// /!\ YOU NEED ACCESS TO STDIN
|
||||||
|
extern int pasm_debug_mode;
|
||||||
|
|
||||||
/* filename: path of the pasm script, will use file argument if NULL */
|
/* filename: path of the pasm script, will use file argument if NULL */
|
||||||
/* file: char** containing the lines of a pasm script, will be used if filename is NULL */
|
/* file: char** containing the lines of a pasm script, will be used if filename is NULL */
|
||||||
/* lines: number of lines in the file argument, will be used if filename is NULL */
|
/* lines: number of lines in the file argument, will be used if filename is NULL */
|
||||||
|
|||||||
170
src/debug.c
Normal file
170
src/debug.c
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
#include "../include/pasm.h"
|
||||||
|
#include "interpreter_states.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
void show_registers() {
|
||||||
|
printf("--Registers--\n");
|
||||||
|
printf("a1: %-3d | ", state->registers->a1);
|
||||||
|
printf("a2: %-3d | ", state->registers->a2);
|
||||||
|
printf("a3: %-3d\n", state->registers->a3);
|
||||||
|
printf("a4: %-3d | ", state->registers->a4);
|
||||||
|
printf("a5: %-3d | ", state->registers->a5);
|
||||||
|
printf("a6: %-3d\n", state->registers->a6);
|
||||||
|
printf("a7: %-3d | ", state->registers->a7);
|
||||||
|
printf("a8: %-3d | ", state->registers->a8);
|
||||||
|
printf("a9: %-3d\n", state->registers->a9);
|
||||||
|
printf("eax: %-3d\n\n", state->registers->eax);
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_stack() {
|
||||||
|
printf("--STACK--\n");
|
||||||
|
printf("Elements: %d\n\n", state->STACK_IDX);
|
||||||
|
for (int i = 0; i < state->STACK_IDX; i++)
|
||||||
|
printf("[%d]: %d\n", i, state->STACK[state->STACK_IDX]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_labels() {
|
||||||
|
printf("\n\n-----LABELS-----\n");
|
||||||
|
printf("format:\tlabel|line");
|
||||||
|
for (int i = 0; i < state->num_labels; i++)
|
||||||
|
printf("%s|%d\n", state->labels[i], state->labels_values[i]);
|
||||||
|
printf("\n\n-----LABELS-----\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_breakpoints(int *bp) {
|
||||||
|
printf("---Breakpoints---\n");
|
||||||
|
for (int i = 0; bp[i] != 0 && i < 255; i++) {
|
||||||
|
if (bp[i] + 1 == -1) continue; //deleted bp
|
||||||
|
printf("bp line %d\n", bp[i] + 1);
|
||||||
|
}
|
||||||
|
printf("---Breakpoints---\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_states() {
|
||||||
|
printf("\n\n--------PASM STATE--------\n");
|
||||||
|
show_registers();
|
||||||
|
show_labels();
|
||||||
|
show_stack();
|
||||||
|
printf("\n\n--------PASM STATE--------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void bp_add(int *bp, int line) {
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0; bp[i] != 0 && bp[i] != -1 && i < 255; i++);
|
||||||
|
bp[i] = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bp_rem(int *bp, int line) {
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0; bp[i] != 0 && i < 255; i++) {
|
||||||
|
if (bp[i] == line)
|
||||||
|
bp[i] = -2;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_breakpoint(char *in, int *bp) {
|
||||||
|
for (int i = 0; i < state->num_labels; i++) {
|
||||||
|
if (strncmp(state->labels[i], in, strlen(in) - 1) == 0) {
|
||||||
|
bp_add(bp, state->labels_values[i] + 1);
|
||||||
|
printf("breakpoint added at line %d.\n", state->labels_values[i] + 2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int line = atoi(in);
|
||||||
|
if (line <= 0 && in[0] != '0')
|
||||||
|
return 1;
|
||||||
|
bp_add(bp, line - 1);
|
||||||
|
printf("breakpoint added at line %d.\n", line);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rem_breakpoint(char *in, int *bp) {
|
||||||
|
for (int i = 0; i < state->num_labels; i++) {
|
||||||
|
if (strncmp(state->labels[i], in, strlen(in) - 1) == 0) {
|
||||||
|
bp_rem(bp, state->labels_values[i] + 1);
|
||||||
|
printf("breakpoint at line %d deleted.\n", state->labels_values[i] + 2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int line = atoi(in);
|
||||||
|
if (line == 0 && in[0] != '0')
|
||||||
|
return 1;
|
||||||
|
bp_rem(bp, line - 1);
|
||||||
|
printf("breakpoint at line %d deleted.\n", line);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void debug_input(char *line) {
|
||||||
|
static int should_continue = 0;
|
||||||
|
static int breakpoints[256] = {0};
|
||||||
|
|
||||||
|
if (should_continue) {
|
||||||
|
for (int i = 0; breakpoints[i] != 0 && i < 255; i++) {
|
||||||
|
if (state->curr_line == breakpoints[i]) {
|
||||||
|
should_continue = 0;
|
||||||
|
printf("breakpoint reached at line %d\n", breakpoints[i] + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (should_continue) return;
|
||||||
|
while (1) {
|
||||||
|
char in[20] = {0};
|
||||||
|
|
||||||
|
printf("\nline %d --> ", state->curr_line + 1);
|
||||||
|
fgets(in, 19, stdin);
|
||||||
|
switch (in[0]) {
|
||||||
|
case 'l':
|
||||||
|
printf("%s\n", line);
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
show_states();
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
should_continue = 1;
|
||||||
|
return;
|
||||||
|
case 's':
|
||||||
|
return;
|
||||||
|
case 'b':
|
||||||
|
in[strlen(in) - 1] = '\0';
|
||||||
|
if (strlen(in) < 3) {
|
||||||
|
printf("command has bad format.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (in[2] == 'l' && strlen(in) == 3) {
|
||||||
|
show_breakpoints(breakpoints);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (add_breakpoint(&in[2], breakpoints))
|
||||||
|
printf("%s is not a valid label or line number in this context", &in[2]);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
in[strlen(in) - 1] = '\0';
|
||||||
|
if (strlen(in) < 3) {
|
||||||
|
printf("command has bad format.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (rem_breakpoint(&in[2], breakpoints))
|
||||||
|
printf("%s is not a valid label or line number in this context", &in[2]);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
state->should_exit = 1;
|
||||||
|
return;
|
||||||
|
case 'h':
|
||||||
|
default:
|
||||||
|
printf("pasm debug mode help message\n");
|
||||||
|
printf("h: shows this message.\n");
|
||||||
|
printf("l: shows current line\n");
|
||||||
|
printf("v: shows states\n");
|
||||||
|
printf("e: end the program\n");
|
||||||
|
printf("c: continue execution until end or breakpoint.\n");
|
||||||
|
printf("s: single step.\n");
|
||||||
|
printf("b [line/label]: sets a breakpoint on line [line/label]\n");
|
||||||
|
printf("b l: list all breakpoints\n");
|
||||||
|
printf("d [line/label]: deletes a breakpoint on line line/label]\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
src/debug.h
Normal file
3
src/debug.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void debug_input(char *line);
|
||||||
23
src/pasm.c
23
src/pasm.c
@@ -2,10 +2,12 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "file_utils.h"
|
#include "file_utils.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "interpreter_states.h"
|
#include "interpreter_states.h"
|
||||||
#include "instructions.h"
|
#include "instructions.h"
|
||||||
|
|
||||||
int fstream = 0;
|
int fstream = 0;
|
||||||
|
int pasm_debug_mode = 0;
|
||||||
void show_error(size_t line, char *line_) {
|
void show_error(size_t line, char *line_) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
int wrote = dprintf(fstream, "%llu| ", line + 1);
|
int wrote = dprintf(fstream, "%llu| ", line + 1);
|
||||||
@@ -19,20 +21,6 @@ void show_error(size_t line, char *line_) {
|
|||||||
dprintf(fstream, " ");
|
dprintf(fstream, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_states() {
|
|
||||||
printf("\n\n--------PASM STATE--------\n");
|
|
||||||
printf("a1: %-3d | ", state->registers->a1);
|
|
||||||
printf("a2: %-3d | ", state->registers->a2);
|
|
||||||
printf("a3: %-3d\n", state->registers->a3);
|
|
||||||
printf("a4: %-3d | ", state->registers->a4);
|
|
||||||
printf("a5: %-3d | ", state->registers->a5);
|
|
||||||
printf("a6: %-3d\n", state->registers->a6);
|
|
||||||
printf("a7: %-3d | ", state->registers->a7);
|
|
||||||
printf("a8: %-3d | ", state->registers->a8);
|
|
||||||
printf("a9: %-3d\n", state->registers->a9);
|
|
||||||
printf("eax: %-3d\n", state->registers->eax);
|
|
||||||
}
|
|
||||||
|
|
||||||
int check_errors(char *line) {
|
int check_errors(char *line) {
|
||||||
if (state->last_check_args_code != OK) {
|
if (state->last_check_args_code != OK) {
|
||||||
show_error(state->curr_line, line);
|
show_error(state->curr_line, line);
|
||||||
@@ -81,9 +69,11 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea
|
|||||||
free_script(file);
|
free_script(file);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int found_main = 0;
|
int found_main = 0;
|
||||||
for (state->curr_line = 0; state->curr_line < (int)lines && get_exit_state() == 0 ; ++state->curr_line) {
|
for (state->curr_line = 0; state->curr_line < (int)lines && get_exit_state() == 0 ; ++state->curr_line) {
|
||||||
|
if (pasm_debug_mode && found_main)
|
||||||
|
debug_input(file[state->curr_line]);
|
||||||
char *line = strdup(file[state->curr_line]);
|
char *line = strdup(file[state->curr_line]);
|
||||||
if (line[0] == ';' || line[0] == '\0') {
|
if (line[0] == ';' || line[0] == '\0') {
|
||||||
free(line);
|
free(line);
|
||||||
@@ -115,9 +105,6 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ret_code = get_exit_state();
|
int ret_code = get_exit_state();
|
||||||
#ifdef DEBUG
|
|
||||||
show_states();
|
|
||||||
#endif
|
|
||||||
free_script(file);
|
free_script(file);
|
||||||
return ret_code;
|
return ret_code;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,13 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if (argc != 2 || strcmp(argv[1], "-h") == 0) {
|
if (argc > 3 || (argc == 2 && strcmp(argv[1], "-h") == 0) || (argc != 2 && argc != 3)) {
|
||||||
fprintf(stderr, "Usage : %s filename\n", argv[0]);
|
fprintf(stderr, "usage : %s filename [-d/--debug]\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (argc == 3 && (strcmp(argv[2], "-d") == 0 || strcmp(argv[2], "--debug") == 0)) {
|
||||||
|
pasm_debug_mode = 1;
|
||||||
|
printf("pasm: debug mode activated.\n");
|
||||||
|
}
|
||||||
return pasm_run_script(argv[1], 0, 0, 1);
|
return pasm_run_script(argv[1], 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user