diff options
author | Marvin Borner | 2021-08-29 13:54:31 +0200 |
---|---|---|
committer | Marvin Borner | 2021-08-29 13:54:31 +0200 |
commit | eef250dd4a0ae185a8d9d668f020b2ab5c2f4849 (patch) | |
tree | e55aca9bfe918c5673ef925cdf373fdff68faafd | |
parent | 7c047df78502d53411fef09c6e39540d2b7e796a (diff) |
Start x86 rewrite
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | bios.bin | bin | 0 -> 131072 bytes | |||
-rw-r--r-- | inc/cpu.h | 8 | ||||
-rw-r--r-- | inc/log.h | 10 | ||||
-rw-r--r-- | src/cpu.c | 83 | ||||
-rw-r--r-- | src/gui.c | 351 | ||||
-rw-r--r-- | src/inc/def.h | 16 | ||||
-rw-r--r-- | src/inc/gui.h | 18 | ||||
-rw-r--r-- | src/inc/lexer.h | 110 | ||||
-rw-r--r-- | src/inc/parser.h | 8 | ||||
-rw-r--r-- | src/inc/syntax.h | 8 | ||||
-rw-r--r-- | src/inc/warnings.h | 17 | ||||
-rw-r--r-- | src/lexer.c | 291 | ||||
-rw-r--r-- | src/log.c | 31 | ||||
-rw-r--r-- | src/main.c | 22 | ||||
-rw-r--r-- | src/parser.c | 666 | ||||
-rw-r--r-- | src/syntax.c | 70 | ||||
-rw-r--r-- | src/warnings.c | 73 | ||||
-rw-r--r-- | test.asm | 4 |
20 files changed, 146 insertions, 1649 deletions
@@ -1,12 +1,13 @@ SOURCEDIR = src +INCDIR = inc BUILDDIR = build SOURCES = $(wildcard $(SOURCEDIR)/*.c) OBJS = $(patsubst $(SOURCEDIR)/%.c, $(BUILDDIR)/%.o, $(SOURCES)) CC = gcc WARNINGS = -Wall -Wextra -Wshadow -Wpointer-arith -Wwrite-strings -Wredundant-decls -Wnested-externs -Wformat=2 -Wmissing-declarations -Wstrict-prototypes -Wmissing-prototypes -Wcast-qual -Wswitch-default -Wswitch-enum -Wlogical-op -Wunreachable-code -Wundef -Wold-style-definition -Wvla -pedantic -DEBUG = -fsanitize=undefined -ggdb3 -g3 -g -s -Og -CFLAGS = -Ofast $(WARNINGS) -I$(SOURCEDIR)/inc/ $(shell pkg-config --cflags --libs gtk+-3.0 gtksourceview-4) $(DEBUG) +DEBUG = -fsanitize=undefined -fsanitize=address -ggdb3 -g3 -g -s -Og +CFLAGS = -Ofast $(WARNINGS) -I$(INCDIR) $(DEBUG) all: $(OBJS) @$(CC) -o ./$(BUILDDIR)/out $^ $(CFLAGS) @@ -1,5 +1,3 @@ # Simsalasim -Don't take this seriously. The code is not supposed to look nice or work without errors (if it works at all). - -Anyhow, it's an 8051 assembler/simulator, nothing more. +It's an x86 simulator, nothing more. diff --git a/bios.bin b/bios.bin Binary files differnew file mode 100644 index 0000000..4f440f1 --- /dev/null +++ b/bios.bin diff --git a/inc/cpu.h b/inc/cpu.h new file mode 100644 index 0000000..fcbb57f --- /dev/null +++ b/inc/cpu.h @@ -0,0 +1,8 @@ +#ifndef CPU_H +#define CPU_H + +int cpu_init(void); +void cpu_run(void); +void cpu_destroy(void); + +#endif diff --git a/inc/log.h b/inc/log.h new file mode 100644 index 0000000..ae55c17 --- /dev/null +++ b/inc/log.h @@ -0,0 +1,10 @@ +#ifndef LOG_H +#define LOG_H + +void __logln(const char *func, const char *format, ...); +void __errln(const char *func, const char *format, ...); + +#define logln(format, ...) __logln(__func__, format, ##__VA_ARGS__) +#define errln(format, ...) __errln(__func__, format, ##__VA_ARGS__) + +#endif diff --git a/src/cpu.c b/src/cpu.c new file mode 100644 index 0000000..ce4410a --- /dev/null +++ b/src/cpu.c @@ -0,0 +1,83 @@ +#include <errno.h> +#include <fcntl.h> +#include <linux/kvm.h> +#include <stdio.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <unistd.h> + +#include <cpu.h> +#include <log.h> + +static int kvm, vm, vcpu; +static struct kvm_run *kvm_run; + +int cpu_init(void) +{ + kvm = open("/dev/kvm", O_RDWR); + if (kvm < 0) { + errln("KVM is required: %s", strerror(errno)); + return -1; + } + + int version = ioctl(kvm, KVM_GET_API_VERSION, 0); + if (version != KVM_API_VERSION) { + close(kvm); + errln("Invalid KVM version: %d", version); + return -1; + } + + vm = ioctl(kvm, KVM_CREATE_VM, 0); + if (vm < 0) { + close(kvm); + errln("Couldn't create VM: %s", strerror(errno)); + return -1; + } + + vcpu = ioctl(vm, KVM_CREATE_VCPU, 0); + if (vcpu < 0) { + close(vm); + close(kvm); + errln("Couldn't create VCPU: %s", strerror(errno)); + return -1; + } + + int mmap_sz = ioctl(kvm, KVM_GET_VCPU_MMAP_SIZE, 0); + if (mmap_sz <= 0 || mmap_sz & 0xfff) { + close(vcpu); + close(vm); + close(kvm); + errln("Invalid mmap_sz: %d", mmap_sz); + return -1; + } + + kvm_run = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE, MAP_SHARED, vcpu, 0); + if (kvm_run == MAP_FAILED) { + close(vcpu); + close(vm); + close(kvm); + errln("Couldn't map kvm_run"); + return -1; + } + + logln("Done"); + return 0; +} + +void cpu_destroy(void) +{ + close(vcpu); + close(vm); + close(kvm); + logln("Done"); +} + +void cpu_run(void) +{ + int run = ioctl(vcpu, KVM_RUN, 0); + if (run < 0) { + errln("CPU can't be run: %s", strerror(errno)); + return; + } +} diff --git a/src/gui.c b/src/gui.c deleted file mode 100644 index 9f2a590..0000000 --- a/src/gui.c +++ /dev/null @@ -1,351 +0,0 @@ -#include <def.h> -#include <gtksourceview/gtksource.h> -#include <gui.h> -#include <parser.h> -#include <stdio.h> -#include <string.h> -#include <syntax.h> - -#define BUFFER_SIZE 1024 - -static GtkWidget *window; -static GtkWidget *text_view; -static char filename[1024] = { 0 }; - -static char *gui_text_buffer(void) -{ - GtkTextIter start, end; - GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); - - gtk_text_buffer_get_bounds(buffer, &start, &end); - gchar *text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); - - return text; // g_free after use! -} - -static void gui_fill_text_view(const char *text) -{ - GtkSourceBuffer *text_buffer = gtk_source_buffer_new(NULL); - gtk_text_buffer_set_text(GTK_TEXT_BUFFER(text_buffer), text, (gint)strlen(text)); - gtk_text_view_set_buffer(GTK_TEXT_VIEW(text_view), GTK_TEXT_BUFFER(text_buffer)); -} - -static void gui_fill_text_view_from_file(const char *path) -{ - char buf[BUFFER_SIZE] = { 0 }; - FILE *test = fopen(path, "r"); - - if (!test) { - gui_show_warning(strerror(errno)); - return; - } - - fread(buf, sizeof(buf), sizeof(buf[0]), test); - fclose(test); - - GtkSourceBuffer *text_buffer = gtk_source_buffer_new(NULL); - gtk_text_buffer_set_text(GTK_TEXT_BUFFER(text_buffer), buf, strnlen(buf, sizeof(buf))); - gtk_text_view_set_buffer(GTK_TEXT_VIEW(text_view), GTK_TEXT_BUFFER(text_buffer)); -} - -static void gui_call_parser(void) -{ - char *buf = gui_text_buffer(); - - if (!parse(buf, BUFFER_SIZE)) { - } // Oh, parsing failed :( (TODO: Do something?) - - g_free(buf); -} - -static void gui_call_syntax_highlighter(void) -{ - char *buf = gui_text_buffer(); - - syntax_highlight(buf, BUFFER_SIZE); - - g_free(buf); -} - -static void gui_init_highlighter(void) -{ - GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); - gtk_text_buffer_create_tag(buffer, "instr", "foreground", "#ff0000", NULL); - gtk_text_buffer_create_tag(buffer, "regs", "foreground", "#00ff00", NULL); -} - -void gui_unhighlight(void) -{ - GtkTextIter start, end; - GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); - - gtk_text_buffer_get_bounds(buffer, &start, &end); - gtk_text_buffer_remove_all_tags(buffer, &start, &end); -} - -void gui_unhighlight_name(const char *tag_name) -{ - GtkTextIter start, end; - GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); - - gtk_text_buffer_get_bounds(buffer, &start, &end); - gtk_text_buffer_remove_tag_by_name(buffer, tag_name, &start, &end); -} - -void gui_highlight(u32 column, u32 line, u32 length, const char *tag_name) -{ - GtkTextIter start, end; - GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); - - gtk_text_buffer_get_iter_at_line_offset(buffer, &start, line, column); - gtk_text_buffer_get_iter_at_line_offset(buffer, &end, line, column + length); - - gtk_text_buffer_apply_tag_by_name(buffer, tag_name, &start, &end); -} - -void gui_show_warning(const char *text) -{ - if (!text) - return; - - GtkWidget *warning = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, - GTK_BUTTONS_OK, "Warning"); - - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(warning), "%s\n", text); - int response = gtk_dialog_run(GTK_DIALOG(warning)); - printf("%d\n", response); - gtk_widget_destroy(warning); -} - -void gui_show_info(const char *text) -{ - if (!text) - return; - - GtkWidget *info = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, - GTK_BUTTONS_OK, "Information"); - - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(info), "%s\n", text); - int response = gtk_dialog_run(GTK_DIALOG(info)); - printf("%d\n", response); - gtk_widget_destroy(info); -} - -static gchar *gui_show_tt(GtkSourceMarkAttributes *attributes, GtkSourceMark *mark, - const gchar *message) -{ - UNUSED(attributes); - UNUSED(mark); - return strdup(message); -} - -void gui_add_line_marker(u32 line_number, const char *message, const char *name, - const char *category, const char *icon, GdkRGBA rgba) -{ - GtkSourceMarkAttributes *attributes = gtk_source_mark_attributes_new(); - gtk_source_mark_attributes_set_background(attributes, &rgba); - gtk_source_mark_attributes_set_icon_name(attributes, icon); - gtk_source_view_set_mark_attributes(GTK_SOURCE_VIEW(text_view), category, attributes, 10); - - GtkTextIter iter; - GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); - gtk_text_buffer_get_iter_at_line(buffer, &iter, line_number); - gtk_source_view_set_mark_attributes(GTK_SOURCE_VIEW(text_view), category, attributes, 10); - gtk_source_buffer_create_source_mark(GTK_SOURCE_BUFFER(buffer), name, category, &iter); - g_signal_connect(G_OBJECT(attributes), "query-tooltip-text", G_CALLBACK(gui_show_tt), - strdup(message)); -} - -void gui_remove_line_marker(const char *category) -{ - GtkTextIter start, end; - GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); - - gtk_text_buffer_get_bounds(buffer, &start, &end); - gtk_source_buffer_remove_source_marks(GTK_SOURCE_BUFFER(buffer), &start, &end, category); -} - -static u8 gui_save_file(char *fname, char *fdata) -{ - FILE *f = fopen(fname, "w"); - if (f == NULL) - return 0; - fputs(fdata, f); - fclose(f); - return 1; -} - -static void gui_show_save_file_dialog(void) -{ - GtkWidget *dialog = - gtk_file_chooser_dialog_new("Save File", GTK_WINDOW(window), - GTK_FILE_CHOOSER_ACTION_SAVE, "Cancel", - GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT, NULL); - GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog); - - gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE); - - char *text; - if (strlen(filename) == 0) { - gtk_file_chooser_set_current_folder(chooser, g_get_home_dir()); - gtk_file_chooser_set_current_name(chooser, "new.asm"); - int res = gtk_dialog_run(GTK_DIALOG(dialog)); - if (res == GTK_RESPONSE_ACCEPT) { - char *savefile = gtk_file_chooser_get_filename(chooser); - strcpy(filename, savefile); - g_free(savefile); - text = gui_text_buffer(); - gtk_widget_destroy(dialog); - } else { - return; - } - } else { - text = gui_text_buffer(); - } - - u8 ret = gui_save_file(filename, text); - g_free(text); - if (ret) - gui_show_info("File saved!"); - else - gui_show_warning("Could not save file!"); -} - -static void gui_show_open_file_dialog(void) -{ - GtkWidget *dialog = - gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(window), - GTK_FILE_CHOOSER_ACTION_OPEN, "Cancel", - GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL); - - int res = gtk_dialog_run(GTK_DIALOG(dialog)); - if (res == GTK_RESPONSE_ACCEPT) { - GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog); - gtk_file_chooser_set_current_folder(chooser, g_get_home_dir()); - char *openfile = gtk_file_chooser_get_filename(chooser); - gui_fill_text_view_from_file(openfile); - strcpy(filename, openfile); - g_free(openfile); - } - - gtk_widget_destroy(dialog); -} - -static void gui_show_new_file_dialog(void) -{ - gui_fill_text_view(""); - memset(filename, 0, sizeof(filename)); -} - -static gboolean gui_key_release_handler(GtkWidget *widget, GdkEventKey *event, gpointer data) -{ - UNUSED(widget); - UNUSED(event); - UNUSED(data); - - // TODO: Integrate highlighting into parser? - //gui_call_syntax_highlighter(); - gui_call_parser(); - - return FALSE; -} - -static void gui_add_menu_item(const char *name, GtkWidget *parent, GtkAccelGroup *accel_group, - GdkModifierType mask_key, guint key, void (*callback)(void)) -{ - GtkWidget *menu_item = gtk_menu_item_new_with_label(name); - g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(callback), NULL); - gtk_widget_add_accelerator(menu_item, "activate", accel_group, key, mask_key, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append(GTK_MENU_SHELL(parent), menu_item); -} - -static void gui_activate(GtkApplication *app, gpointer data) -{ - UNUSED(data); - - // Initialize window - window = gtk_application_window_new(app); - gtk_window_set_title(GTK_WINDOW(window), "simsalasim"); - gtk_window_set_default_size(GTK_WINDOW(window), 400, 400); - - // Key press listener - g_signal_connect(window, "key_release_event", G_CALLBACK(gui_key_release_handler), NULL); - - // Main container - GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - gtk_container_add(GTK_CONTAINER(window), box); - - // Keyboard shortcut map init - GtkAccelGroup *accel_group = gtk_accel_group_new(); - gtk_window_add_accel_group(GTK_WINDOW(window), accel_group); - - // Very cool menu bar - GtkWidget *menu_bar = gtk_menu_bar_new(); - // File menu - GtkWidget *file_menu = gtk_menu_new(); - GtkWidget *file_tab = gtk_menu_item_new_with_label("File"); - - gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_tab), file_menu); - - gui_add_menu_item("New", file_menu, accel_group, GDK_CONTROL_MASK, GDK_KEY_N, - gui_show_new_file_dialog); - gui_add_menu_item("Open", file_menu, accel_group, GDK_CONTROL_MASK, GDK_KEY_O, - gui_show_open_file_dialog); - gui_add_menu_item("Save", file_menu, accel_group, GDK_CONTROL_MASK, GDK_KEY_S, - gui_show_save_file_dialog); - - gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), file_tab); - - GtkWidget *run_menu = gtk_menu_new(); - GtkWidget *run_tab = gtk_menu_item_new_with_label("Run"); - - gtk_menu_item_set_submenu(GTK_MENU_ITEM(run_tab), run_menu); - - gui_add_menu_item("Compile", run_menu, accel_group, GDK_CONTROL_MASK, GDK_KEY_Return, - gui_call_parser); - - gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), run_tab); - - gtk_container_add(GTK_CONTAINER(box), menu_bar); - - // Strange text view - text_view = gtk_source_view_new(); - gtk_source_view_set_show_line_numbers(GTK_SOURCE_VIEW(text_view), TRUE); - gtk_source_view_set_auto_indent(GTK_SOURCE_VIEW(text_view), TRUE); - gtk_source_view_set_show_line_marks(GTK_SOURCE_VIEW(text_view), TRUE); - gtk_box_pack_end(GTK_BOX(box), text_view, TRUE, TRUE, 0); - - // Font - GtkCssProvider *provider = gtk_css_provider_new(); - gtk_css_provider_load_from_data( - provider, "textview { font-family: Monospace; font-size: 11pt; }", -1, NULL); - gtk_style_context_add_provider(gtk_widget_get_style_context(text_view), - GTK_STYLE_PROVIDER(provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - g_object_unref(provider); - - // Show all widgets! - gtk_widget_show_all(window); - - // Only for testing purposes - gui_fill_text_view_from_file("test.asm"); - - gui_init_highlighter(); - gui_call_syntax_highlighter(); -} - -int gui_init(int argc, char *argv[]) -{ - gtk_init(&argc, &argv); - - g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme", TRUE, NULL); - - GtkApplication *app = - gtk_application_new("de.melvars.simsalasim", G_APPLICATION_FLAGS_NONE); - g_signal_connect(app, "activate", G_CALLBACK(gui_activate), NULL); - int status = g_application_run(G_APPLICATION(app), argc, argv); - g_object_unref(app); - - return status; -} diff --git a/src/inc/def.h b/src/inc/def.h deleted file mode 100644 index 22e1bda..0000000 --- a/src/inc/def.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef DEF_H -#define DEF_H - -typedef unsigned int u32; -typedef unsigned short u16; -typedef unsigned char u8; - -typedef signed int s32; -typedef signed short s16; -typedef signed char s8; - -#define UNUSED(bla) ((void)(bla)) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) - -#endif diff --git a/src/inc/gui.h b/src/inc/gui.h deleted file mode 100644 index 39918ca..0000000 --- a/src/inc/gui.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef GUI_H -#define GUI_H - -#include <def.h> -#include <gtk/gtk.h> - -int gui_init(int argc, char *argv[]); -void gui_show_warning(const char *text); -void gui_show_info(const char *text); - -void gui_add_line_marker(u32 line_number, const char *message, const char *name, const char *category, const char *icon, GdkRGBA rgba); -void gui_remove_line_marker(const char *category); - -void gui_unhighlight(void); -void gui_unhighlight_name(const char *tag_name); -void gui_highlight(u32 column, u32 line, u32 length, const char *color); - -#endif diff --git a/src/inc/lexer.h b/src/inc/lexer.h deleted file mode 100644 index 33b56af..0000000 --- a/src/inc/lexer.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef LEXER_H -#define LEXER_H - -#include <def.h> - -enum token_type { - UNKNOWN, - NEWLINE, - END, - SPACE, - - INSTR_START, - NOP, - JBC, - JB, - JNB, - JC, - JNC, - JZ, - JNZ, - SJMP, - MOV, - ORL, - ANL, - PUSH, - POP, - MOVX, - AJMP, - ACALL, - LJMP, - LCALL, - RETI, - RET, - XRL, - CPL, - CLR, - SETB, - RR, - RRC, - RL, - RLC, - XLR, - JMP, - MOVC, - INC, - DEC, - ADD, - ADDC, - DIV, - DUBB, - MUL, - CJNE, - SWAP, - DA, - CRL, - XCH, - DJNZ, - XCHD, - CALL, - ORG, - DB, - DW, - DATA, - BIT, - INCLUDE, - INSTR_END, - - HASH, - DOLLAR, - SLASH, - PLUS, - COMMA, - DOT, - COLON, - SEMICOLON, - - NUM_START, - DEC_NUM, - HEX_NUM, - BIN_NUM, - NUM_END, - - STRING, - - // Registers - REGS_START, - ACCU, - ATR0, - ATR1, - R0, - R1, - R2, - R3, - R4, - R5, - R6, - R7, - REGS_END, -}; - -struct token { - enum token_type type; - char *start; - u32 length; -}; - -void token_print(struct token *tok); -struct token token_resolve(char *token, u32 size); - -#endif diff --git a/src/inc/parser.h b/src/inc/parser.h deleted file mode 100644 index 0c59681..0000000 --- a/src/inc/parser.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef PARSER_H -#define PARSER_H - -#include <def.h> - -u8 parse(char *buf, u32 size); - -#endif diff --git a/src/inc/syntax.h b/src/inc/syntax.h deleted file mode 100644 index 7857d75..0000000 --- a/src/inc/syntax.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef SYNTAX_H -#define SYNTAX_H - -#include <def.h> - -void syntax_highlight(char *buf, u32 size); - -#endif diff --git a/src/inc/warnings.h b/src/inc/warnings.h deleted file mode 100644 index 76da8b4..0000000 --- a/src/inc/warnings.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef WARNINGS_H -#define WARNINGS_H - -#include <def.h> - -struct context { - u32 line; - u32 column; -}; - -void warnings_print(void); -void warnings_add(struct context *ctx, const char *fmt, ...); -void warnings_clear(void); -void warnings_remove_marks(void); -u8 warnings_exist(void); - -#endif diff --git a/src/lexer.c b/src/lexer.c deleted file mode 100644 index 9efe957..0000000 --- a/src/lexer.c +++ /dev/null @@ -1,291 +0,0 @@ -#include <assert.h> -#include <def.h> -#include <lexer.h> -#include <stdio.h> -#include <string.h> - -#define ALPHA(a) (((a) >= 'a' && (a) <= 'z') || ((a) >= 'A' && (a) <= 'Z')) -#define NUMERIC(a) ((a) >= '0' && (a) <= '9') -#define ALPHA_NUMERIC(a) (ALPHA(a) || NUMERIC(a)) -#define HEX_NUMERIC(a) (NUMERIC(a) || ((a) >= 'a' && (a) <= 'f') || ((a) >= 'A' && (a) <= 'F')) - -#define CMPSP(tok) \ - (strncasecmp(tok " ", str, MIN(strlen(tok) + 1, size)) == 0) // CMP with space at end -#define CMPNA(tok) \ - (strncasecmp(tok, str, MIN(strlen(tok), size)) == 0 && \ - !ALPHA(str[strlen(tok)])) // CMP with non alpha at end - -void token_print(struct token *tok) -{ - // Something terrible needs to happen to make this true - assert(tok->length || tok->type == END); - - if (tok->type == END) { - printf("\\0 (%d)\n", tok->type); - return; - } - - char swp = tok->start[tok->length]; - tok->start[tok->length] = 0; - printf("%s (%d)\n", tok->start, tok->type); - tok->start[tok->length] = swp; -} - -struct token token_resolve(char *str, u32 size) -{ - enum token_type type = UNKNOWN; - u32 length = 0; - - // "Beautiful" ~ Everyone. Probably. - if (NUMERIC(str[0])) { - while (HEX_NUMERIC(str[length])) - length++; - - if (str[length] == 'h' || str[length] == 'H') { - type = HEX_NUM; - length++; - } else if (str[length] == 'b' || str[length] == 'B') { - type = BIN_NUM; - length++; - } else { - type = DEC_NUM; - } - } else if (str[0] == '\n') { - type = NEWLINE; - length = 1; - } else if (str[0] == '\0') { - type = END; - length = 0; // Well - } else if (str[0] == ' ') { - type = SPACE; - length = 1; - } else if (str[0] == ',') { - type = COMMA; - length = 1; - } else if (str[0] == '$') { - type = DOLLAR; - length = 1; - } else if (str[0] == '/') { - type = SLASH; - length = 1; - } else if (str[0] == '+') { - type = PLUS; - length = 1; - } else if (str[0] == '.') { - type = DOT; - length = 1; - } else if (str[0] == ':') { - type = COLON; - length = 1; - } else if (str[0] == ';') { - type = SEMICOLON; - length = 1; - } else if (str[0] == '#') { - type = HASH; - length = 1; - } else if (str[0] == 'A' && !ALPHA(str[1])) { - type = ACCU; - length = 1; - } else if (CMPNA("R0")) { - type = R0; - length = 2; - } else if (CMPNA("R1")) { - type = R1; - length = 2; - } else if (CMPNA("R2")) { - type = R2; - length = 2; - } else if (CMPNA("R3")) { - type = R3; - length = 2; - } else if (CMPNA("R4")) { - type = R4; - length = 2; - } else if (CMPNA("R5")) { - type = R5; - length = 2; - } else if (CMPNA("R6")) { - type = R6; - length = 2; - } else if (CMPNA("R7")) { - type = R7; - length = 2; - } else if (CMPSP("nop")) { - type = NOP; - length = 3; - } else if (CMPSP("jbc")) { - type = JBC; - length = 3; - } else if (CMPSP("jb")) { - type = JB; - length = 2; - } else if (CMPSP("jnb")) { - type = JNB; - length = 3; - } else if (CMPSP("jc")) { - type = JC; - length = 2; - } else if (CMPSP("jnc")) { - type = JNC; - length = 3; - } else if (CMPSP("jz")) { - type = JZ; - length = 2; - } else if (CMPSP("jnz")) { - type = JNZ; - length = 3; - } else if (CMPSP("sjmp")) { - type = SJMP; - length = 4; - } else if (CMPSP("mov")) { - type = MOV; - length = 3; - } else if (CMPSP("orl")) { - type = ORL; - length = 3; - } else if (CMPSP("anl")) { - type = ANL; - length = 3; - } else if (CMPSP("push")) { - type = PUSH; - length = 4; - } else if (CMPSP("pop")) { - type = POP; - length = 3; - } else if (CMPSP("movx")) { - type = MOVX; - length = 4; - } else if (CMPSP("ajmp")) { - type = AJMP; - length = 4; - } else if (CMPSP("acall")) { - type = ACALL; - length = 5; - } else if (CMPSP("ljmp")) { - type = LJMP; - length = 4; - } else if (CMPSP("lcall")) { - type = LCALL; - length = 5; - } else if (CMPSP("reti")) { - type = RETI; - length = 4; - } else if (CMPSP("ret")) { - type = RET; - length = 3; - } else if (CMPSP("xrl")) { - type = XRL; - length = 3; - } else if (CMPSP("cpl")) { - type = CPL; - length = 3; - } else if (CMPSP("clr")) { - type = CLR; - length = 3; - } else if (CMPSP("setb")) { - type = SETB; - length = 4; - } else if (CMPSP("rr")) { - type = RR; - length = 2; - } else if (CMPSP("rrc")) { - type = RRC; - length = 3; - } else if (CMPSP("rl")) { - type = RL; - length = 2; - } else if (CMPSP("rlc")) { - type = RLC; - length = 3; - } else if (CMPSP("xlr")) { - type = XLR; - length = 3; - } else if (CMPSP("jmp")) { - type = JMP; - length = 3; - } else if (CMPSP("movc")) { - type = MOVC; - length = 4; - } else if (CMPSP("inc")) { - type = INC; - length = 3; - } else if (CMPSP("dec")) { - type = DEC; - length = 3; - } else if (CMPSP("add")) { - type = ADD; - length = 3; - } else if (CMPSP("addc")) { - type = ADDC; - length = 4; - } else if (CMPSP("div")) { - type = DIV; - length = 3; - } else if (CMPSP("dubb")) { - type = DUBB; - length = 4; - } else if (CMPSP("mul")) { - type = MUL; - length = 3; - } else if (CMPSP("cjne")) { - type = CJNE; - length = 4; - } else if (CMPSP("swap")) { - type = SWAP; - length = 4; - } else if (CMPSP("da")) { - type = DA; - length = 2; - } else if (CMPSP("crl")) { - type = CRL; - length = 3; - } else if (CMPSP("xch")) { - type = XCH; - length = 3; - } else if (CMPSP("djnz")) { - type = DJNZ; - length = 4; - } else if (CMPSP("xchd")) { - type = XCHD; - length = 4; - } else if (CMPSP("call")) { - type = CALL; - length = 4; - } else if (CMPSP("org")) { - type = ORG; - length = 3; - } else if (CMPSP("db")) { - type = DB; - length = 2; - } else if (CMPSP("dw")) { - type = DW; - length = 2; - } else if (CMPSP("data")) { // Lars: "Who cares?" - type = DATA; - length = 4; - } else if (CMPSP("bit")) { - type = BIT; - length = 3; - } else if (CMPSP("include")) { - type = INCLUDE; - length = 7; - } else { - if (ALPHA(str[0])) { - while (ALPHA_NUMERIC(str[length])) - length++; - - if (length) { - type = STRING; - length++; - } - } - } - - struct token tok = { - .type = type, - .start = str, - .length = length, - }; - - return tok; -} diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..dd3c33e --- /dev/null +++ b/src/log.c @@ -0,0 +1,31 @@ +#include <stdarg.h> +#include <stdio.h> + +#include <log.h> + +#define LOG_OUT stdout +#define ERR_OUT stderr + +void __logln(const char *func, const char *format, ...) +{ + fprintf(LOG_OUT, "[LOG] %s: ", func); + + va_list ap; + va_start(ap, format); + vfprintf(LOG_OUT, format, ap); + va_end(ap); + + fprintf(LOG_OUT, "\n"); +} + +void __errln(const char *func, const char *format, ...) +{ + fprintf(ERR_OUT, "[ERR] %s: ", func); + + va_list ap; + va_start(ap, format); + vfprintf(ERR_OUT, format, ap); + va_end(ap); + + fprintf(ERR_OUT, "\n"); +} @@ -1,18 +1,16 @@ -#include <gui.h> -#include <stdio.h> +#include <cpu.h> #include <stdlib.h> -#include <string.h> - -static void print_help(void) -{ - printf("Help\n"); - exit(0); -} int main(int argc, char *argv[]) { - if (argc == 2 && (strcmp(argv[1], "--help") == 0)) - print_help(); + (void)argc; + (void)argv; + + int cpu = cpu_init(); + if (cpu < 0) + exit(1); + cpu_run(); + cpu_destroy(); - return gui_init(argc, argv); + return 0; } diff --git a/src/parser.c b/src/parser.c deleted file mode 100644 index e998135..0000000 --- a/src/parser.c +++ /dev/null @@ -1,666 +0,0 @@ -#include <assert.h> -#include <def.h> -#include <lexer.h> -#include <parser.h> -#include <stdio.h> -#include <string.h> -#include <warnings.h> - -/** - * Definitions - */ - -#define ROM_SIZE 4096 // TODO: Actual ROM size? - -/** - * ROM blub blabs - */ - -static u8 rom[ROM_SIZE] = { 0 }; -static u32 rom_index = 0; -static void rom_add(u8 byte) -{ - rom[rom_index] = byte; - rom_index++; -} - -/** - * Toks parsing - */ - -static u32 toks_count(struct token *toks) -{ - struct token *p = toks; - while (p && p->type != END && p->type != UNKNOWN && p->type != NEWLINE) - p++; - return p - toks; -} - -static struct token *toks_peek(struct token *toks, u32 cnt) -{ - return toks + cnt; -} - -static struct token *toks_peek_end(struct token *toks) -{ - return toks + toks_count(toks) - 1; -} - -/** - * Main parsing - */ - -static void parse_nop(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); - rom_add(0); -} - -static void parse_jbc(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_jb(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_jnb(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_jc(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_jnc(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_jz(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_jnz(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_sjmp(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_mov(struct context *ctx, struct token *toks) -{ - if (toks_peek_end(toks)->type == COMMA) - warnings_add(ctx, "Unexpected end of line"); - else if (toks_count(toks) > 5) - warnings_add(ctx, "Too many arguments"); -} - -static void parse_orl(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_anl(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_push(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_pop(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_movx(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_ajmp(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_acall(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_ljmp(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_lcall(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_reti(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_ret(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_xrl(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_cpl(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_clr(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_setb(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_rr(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_rrc(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_rl(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_rlc(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_xlr(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_jmp(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_movc(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_inc(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_dec(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_add(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_addc(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_div(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_dubb(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_mul(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_cjne(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_swap(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_da(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_crl(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_xch(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_djnz(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_xchd(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_call(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_org(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_db(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_dw(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_include(struct context *ctx, struct token *toks) -{ - UNUSED(ctx); - UNUSED(toks); -} - -static void parse_string(struct context *ctx, struct token *toks) -{ - enum token_type next = toks_peek(toks, 1)->type; - if (next == COLON) { - // TODO: Add label lookup tables - } else if (next == DATA) { - // TODO: Constants map - } else if (next == BIT) { - // TODO: Constants map - } else { - warnings_add(ctx, "Expected data/bit/colon"); - } -} - -static u32 parse_line(struct context *ctx, char *str, u32 size) -{ - struct token toks[32] = { 0 }; - u8 tok_ind = 0; - u8 str_ind = 0; - - while (1) { - struct token tok = token_resolve(str + str_ind, size - str_ind); - if (tok.type == NEWLINE) { - ctx->line++; - ctx->column = 0; - break; - } - - if (tok.type == UNKNOWN) - break; - - if (tok.type == END) { - ctx->line++; - break; - } - - if (tok.type == SPACE) { - str_ind += tok.length; - continue; - } - - token_print(&tok); - - if (tok_ind + 1 >= (u8)(sizeof(toks) / sizeof(toks[0]))) { - warnings_add(ctx, "Token overflow"); - return str_ind; - } - - toks[tok_ind++] = tok; - str_ind += tok.length; - } - - ctx->column = str_ind; - - if (!tok_ind) { - warnings_add(ctx, "Parsing failed"); - return str_ind; - } - - switch (toks[0].type) { - case UNKNOWN: - warnings_add(ctx, "Unknown instruction"); - break; - case NEWLINE: - break; - case NOP: - parse_nop(ctx, toks); - break; - case JBC: - parse_jbc(ctx, toks); - break; - case JB: - parse_jb(ctx, toks); - break; - case JNB: - parse_jnb(ctx, toks); - break; - case JC: - parse_jc(ctx, toks); - break; - case JNC: - parse_jnc(ctx, toks); - break; - case JZ: - parse_jz(ctx, toks); - break; - case JNZ: - parse_jnz(ctx, toks); - break; - case SJMP: - parse_sjmp(ctx, toks); - break; - case MOV: - parse_mov(ctx, toks); - break; - case ORL: - parse_orl(ctx, toks); - break; - case ANL: - parse_anl(ctx, toks); - break; - case PUSH: - parse_push(ctx, toks); - break; - case POP: - parse_pop(ctx, toks); - break; - case MOVX: - parse_movx(ctx, toks); - break; - case AJMP: - parse_ajmp(ctx, toks); - break; - case ACALL: - parse_acall(ctx, toks); - break; - case LJMP: - parse_ljmp(ctx, toks); - break; - case LCALL: - parse_lcall(ctx, toks); - break; - case RETI: - parse_reti(ctx, toks); - break; - case RET: - parse_ret(ctx, toks); - break; - case XRL: - parse_xrl(ctx, toks); - break; - case CPL: - parse_cpl(ctx, toks); - break; - case CLR: - parse_clr(ctx, toks); - break; - case SETB: - parse_setb(ctx, toks); - break; - case RR: - parse_rr(ctx, toks); - break; - case RRC: - parse_rrc(ctx, toks); - break; - case RL: - parse_rl(ctx, toks); - break; - case RLC: - parse_rlc(ctx, toks); - break; - case XLR: - parse_xlr(ctx, toks); - break; - case JMP: - parse_jmp(ctx, toks); - break; - case MOVC: - parse_movc(ctx, toks); - break; - case INC: - parse_inc(ctx, toks); - break; - case DEC: - parse_dec(ctx, toks); - break; - case ADD: - parse_add(ctx, toks); - break; - case ADDC: - parse_addc(ctx, toks); - break; - case DIV: - parse_div(ctx, toks); - break; - case DUBB: - parse_dubb(ctx, toks); - break; - case MUL: - parse_mul(ctx, toks); - break; - case CJNE: - parse_cjne(ctx, toks); - break; - case SWAP: - parse_swap(ctx, toks); - break; - case DA: - parse_da(ctx, toks); - break; - case CRL: - parse_crl(ctx, toks); - break; - case XCH: - parse_xch(ctx, toks); - break; - case DJNZ: - parse_djnz(ctx, toks); - break; - case XCHD: - parse_xchd(ctx, toks); - break; - case CALL: - parse_call(ctx, toks); - break; - case ORG: - parse_org(ctx, toks); - break; - case DB: - parse_db(ctx, toks); - break; - case DW: - parse_dw(ctx, toks); - break; - case INCLUDE: - parse_include(ctx, toks); - break; - case STRING: - parse_string(ctx, toks); - break; - case SPACE: - case HASH: - case DOLLAR: - case SLASH: - case PLUS: - case COMMA: - case DOT: - case COLON: - case SEMICOLON: - case DEC_NUM: - case HEX_NUM: - case BIN_NUM: - case ACCU: - case ATR0: - case ATR1: - case R0: - case R1: - case R2: - case R3: - case R4: - case R5: - case R6: - case R7: - case DATA: - case BIT: - warnings_add(ctx, "Random non-instruction found"); - break; - case INSTR_START: - case INSTR_END: - case NUM_START: - case NUM_END: - case REGS_START: - case REGS_END: - case END: - warnings_add(ctx, "Got enum boundary"); - break; - default: - warnings_add(ctx, "Super-unknown instruction"); - break; - } - - return str_ind; -} - -static void clean_buffers(void) -{ - if (rom_index) - memset(rom, 0, sizeof(rom)); - warnings_clear(); -} - -u8 parse(char *buf, u32 size) -{ - clean_buffers(); - - struct context ctx = { .line = 0, .column = 0 }; - - for (u32 i = 0; i < size; i++) { - if (buf[i] == '\0') - break; - - if (buf[i] == '\n') { - ctx.line++; - ctx.column = 0; - continue; - } - - u32 len = parse_line(&ctx, buf + i, size - i); - i += len; - ctx.column += len; - - if (buf[i] == '\0') - break; - } - - if (warnings_exist()) { - warnings_print(); - return 0; - } else { - warnings_remove_marks(); - } - - return 1; -} diff --git a/src/syntax.c b/src/syntax.c deleted file mode 100644 index 8dbc16f..0000000 --- a/src/syntax.c +++ /dev/null @@ -1,70 +0,0 @@ -#include <def.h> -#include <gui.h> -#include <lexer.h> -#include <stdio.h> -#include <syntax.h> - -struct pos { - u32 x; - u32 y; -}; - -static void syntax_highlight_line(struct pos *pos, char *str, u32 size) -{ - /* printf("Got size %d '", size); */ - /* for (u32 i = 0; i < size; i++) { */ - /* printf("%c", str[i]); */ - /* } */ - /* printf("'\n"); */ - - while (1) { - struct token tok = token_resolve(str + pos->x, size - pos->x); - - if (tok.type == NEWLINE) { - pos->x = 0; - pos->y++; - return; - } - - if (tok.type == UNKNOWN) - return; - - if (tok.type == SPACE) { - pos->x += tok.length; - continue; - } - - /* token_print(&tok); */ - - if (tok.type > INSTR_START && tok.type < INSTR_END) - gui_highlight(pos->x, pos->y, tok.length, "instr"); - else if (tok.type > REGS_START && tok.type < REGS_END) - gui_highlight(pos->x, pos->y, tok.length, "regs"); - - pos->x += tok.length; - } -} - -void syntax_highlight(char *buf, u32 size) -{ - return; - struct pos pos = { 0 }; - - u32 diff = 0; - char *start = buf; - gui_unhighlight(); - for (u32 i = 0; i < size; i++) { - // TODO: Fix highlighting of last line without \n - if (buf[i] == '\0') - break; - - if (buf[i] == '\n') { - pos.x = 0; - syntax_highlight_line(&pos, start, diff); - start += diff + 1; - diff = 0; - } else { - diff++; - } - } -} diff --git a/src/warnings.c b/src/warnings.c deleted file mode 100644 index 47566ba..0000000 --- a/src/warnings.c +++ /dev/null @@ -1,73 +0,0 @@ -#include <assert.h> -#include <def.h> -#include <gui.h> -#include <stdarg.h> -#include <stdio.h> -#include <string.h> -#include <warnings.h> - -#define WARNING_COUNT 1024 // Well, something went horribly wrong I guess -#define WARNING_LENGTH 64 - -struct warning { - u8 exists; - struct context ctx; - char text[WARNING_LENGTH]; - char name[8]; -}; - -static struct warning warnings[WARNING_COUNT] = { 0 }; -static u32 warning_index = 0; -void warnings_add(struct context *ctx, const char *fmt, ...) -{ - assert(warning_index + 1 < WARNING_COUNT); - - warnings[warning_index].exists = 1; - warnings[warning_index].ctx = *ctx; - - va_list ap; - va_start(ap, fmt); - vsnprintf(warnings[warning_index].text, WARNING_LENGTH, fmt, ap); - va_end(ap); - - warning_index++; -} - -static void warnings_generate_name(u32 i) -{ - static u32 ctr = 0; - snprintf(warnings[i].name, 8, "%d", ctr++); -} - -void warnings_remove_marks(void) -{ - gui_remove_line_marker("warning"); -} - -void warnings_print(void) -{ - warnings_remove_marks(); - for (u32 i = 0; i < WARNING_COUNT; i++) { - if (!warnings[i].exists) - continue; - - printf("Line %d:%d: %s\n", warnings[i].ctx.line, warnings[i].ctx.column, - warnings[i].text); - warnings_generate_name(i); - gui_add_line_marker(warnings[i].ctx.line - 1, warnings[i].text, warnings[i].name, - "warning", "dialog-warning", (GdkRGBA){ 1, 0, 0, .3 }); - } -} - -u8 warnings_exist(void) -{ - return warning_index > 0; -} - -void warnings_clear(void) -{ - if (warnings_exist()) { - memset(warnings, 0, sizeof(warnings)); - warning_index = 0; - } -} diff --git a/test.asm b/test.asm deleted file mode 100644 index f834fd5..0000000 --- a/test.asm +++ /dev/null @@ -1,4 +0,0 @@ -P0 DATA 080h - -mov A, #42 -jmp $ |