Files
nunuhara_xsystem4/debugger.c
T
Nunuhara Cabbage fd57ca7845 Fix loading of arrays
Array rank can't be inferred from JSON data since arrays and structs are
indistinguishable. So we get it from the ain file instead.

Sengoku Rance is mostly playable as of this commit.
2019-12-21 11:52:48 -08:00

144 lines
3.7 KiB
C

/* Copyright (C) 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://gnu.org/licenses/>.
*/
#include <stdio.h>
#include <chibi/eval.h>
#include "vm.h"
#include "page.h"
#include "utfsjis.h"
struct variable {
enum ain_data_type data_type;
int struct_type;
char *name;
int varno;
union vm_value *value;
};
static void free_variable(struct variable *v)
{
free(v->name);
free(v);
}
static char *to_utf(const char *sjis)
{
return sjis2utf(sjis, strlen(sjis));
}
static const char *vm_value_string(union vm_value *v)
{
return to_utf(heap[v->i].s->text);
}
static struct page *get_page(int pageno)
{
if (!page_index_valid(pageno))
return NULL;
return vm_get_page(pageno);
}
static struct variable *get_global_by_name(const char *name)
{
for (int i = 0; i < ain->nr_globals; i++) {
if (!strcmp(ain->globals[i].name, name)) {
struct variable *v = malloc(sizeof(struct variable));
v->data_type = ain->globals[i].data_type;
v->struct_type = ain->globals[i].struct_type;
v->name = to_utf(ain->globals[i].name);
v->varno = i;
v->value = &heap[0].page->values[i];
return v;
}
}
return NULL;
}
static struct variable *get_local_by_name(const char *name)
{
struct page *page = local_page();
struct ain_function *f = &ain->functions[page->index];
for (int i = 0; i < f->nr_vars; i++) {
if (!strcmp(f->vars[i].name, name)) {
struct variable *v = malloc(sizeof(struct variable));
v->data_type = f->vars[i].data_type;
v->struct_type = f->vars[i].struct_type;
v->name = to_utf(ain->globals[i].name);
v->varno = i;
v->value = &page->values[i];
return v;
}
}
return NULL;
}
static const char *variable_name(struct page *page, int varno)
{
switch (page->type) {
case GLOBAL_PAGE:
return ain->globals[varno].name;
case LOCAL_PAGE:
return ain->functions[page->index].vars[varno].name;
case STRUCT_PAGE:
return ain->structures[page->index].members[varno].name;
case ARRAY_PAGE:
return "array member";
}
return "unknown";
}
static struct variable *page_ref(struct page *page, int i)
{
if (i < 0 || i >= page->nr_vars)
return NULL;
struct variable *v = malloc(sizeof(struct variable));
v->data_type = variable_type(page, i, &v->struct_type, NULL);
v->name = to_utf(variable_name(page, i));
v->varno = i;
v->value = &page->values[i];
return v;
}
#include "debug-ffi.c"
static sexp dbg_ctx;
void dbg_init(void)
{
dbg_ctx = sexp_make_eval_context(NULL, NULL, NULL, 0, 0);
sexp_load_standard_env(dbg_ctx, NULL, SEXP_SEVEN);
sexp_load_standard_ports(dbg_ctx, NULL, stdin, stdout, stderr, 1);
sexp_init_library(dbg_ctx, NULL, 0, sexp_context_env(dbg_ctx), sexp_version, SEXP_ABI_IDENTIFIER);
sexp_eval_string(dbg_ctx, "(import (scheme base))", -1, NULL);
sexp_eval_string(dbg_ctx, "(import (chibi repl))", -1, NULL);
sexp_eval_string(dbg_ctx, "(define *prompt* (make-parameter \"dbg> \"))", -1, NULL);
sexp_eval_string(dbg_ctx, "(define (repl-make-prompt m) (*prompt*))", -1, NULL);
sexp_eval_string(dbg_ctx, "(load \"./debugger.scm\")", -1, NULL);
}
void dbg_fini(void)
{
sexp_destroy_context(dbg_ctx);
}
void dbg_repl(void)
{
sexp_eval_string(dbg_ctx, "(repl 'escape: #\\\\ 'make-prompt: repl-make-prompt)", -1, NULL);
}