diff --git a/debugger.c b/debugger.c index 0796121..770693a 100644 --- a/debugger.c +++ b/debugger.c @@ -108,7 +108,7 @@ static struct variable *page_ref(struct page *page, int i) return NULL; struct variable *v = malloc(sizeof(struct variable)); - v->data_type = variable_type(page, i, &v->struct_type); + 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]; diff --git a/page.c b/page.c index 8863732..149ccf6 100644 --- a/page.c +++ b/page.c @@ -141,24 +141,32 @@ enum ain_data_type array_type(enum ain_data_type type) } } -enum ain_data_type variable_type(struct page *page, int varno, int *struct_type) +enum ain_data_type variable_type(struct page *page, int varno, int *struct_type, int *array_rank) { switch (page->type) { case GLOBAL_PAGE: if (struct_type) *struct_type = ain->globals[varno].struct_type; + if (array_rank) + *array_rank = ain->globals[varno].array_dimensions; return ain->globals[varno].data_type; case LOCAL_PAGE: if (struct_type) *struct_type = ain->functions[page->index].vars[varno].struct_type; + if (array_rank) + *array_rank = ain->functions[page->index].vars[varno].array_dimensions; return ain->functions[page->index].vars[varno].data_type; case STRUCT_PAGE: if (struct_type) *struct_type = ain->structures[page->index].members[varno].struct_type; + if (array_rank) + *array_rank = ain->structures[page->index].members[varno].array_dimensions; return ain->structures[page->index].members[varno].data_type; case ARRAY_PAGE: if (struct_type) *struct_type = page->struct_type; + if (array_rank) + *array_rank = page->rank - 1; return page->rank > 1 ? page->a_type : array_type(page->a_type); } return AIN_VOID; @@ -167,7 +175,7 @@ enum ain_data_type variable_type(struct page *page, int varno, int *struct_type) void delete_page(struct page *page) { for (int i = 0; i < page->nr_vars; i++) { - variable_fini(page->values[i], variable_type(page, i, NULL)); + variable_fini(page->values[i], variable_type(page, i, NULL, NULL)); } } @@ -182,7 +190,7 @@ struct page *copy_page(struct page *src) dst->struct_type = src->struct_type; dst->rank = src->rank; for (int i = 0; i < src->nr_vars; i++) { - dst->values[i] = vm_copy(src->values[i], variable_type(src, i, NULL)); + dst->values[i] = vm_copy(src->values[i], variable_type(src, i, NULL, NULL)); } return dst; } @@ -221,7 +229,7 @@ void create_struct(int no, union vm_value *var) init_struct(no, var->i); } -struct page *alloc_array(int rank, union vm_value *dimensions, int data_type, int struct_type, bool init_structs) +struct page *alloc_array(int rank, union vm_value *dimensions, enum ain_data_type data_type, int struct_type, bool init_structs) { if (rank < 1) return NULL; @@ -247,7 +255,7 @@ struct page *alloc_array(int rank, union vm_value *dimensions, int data_type, in return page; } -struct page *realloc_array(struct page *src, int rank, union vm_value *dimensions, int data_type, int struct_type, bool init_structs) +struct page *realloc_array(struct page *src, int rank, union vm_value *dimensions, enum ain_data_type data_type, int struct_type, bool init_structs) { if (rank < 1) ERROR("Tried to allocate 0-rank array"); @@ -267,7 +275,7 @@ struct page *realloc_array(struct page *src, int rank, union vm_value *dimension // if shrinking array, unref orphaned children if (dimensions->i < src->nr_vars) { for (int i = dimensions->i; i < src->nr_vars; i++) { - variable_fini(src->values[i], variable_type(src, i, NULL)); + variable_fini(src->values[i], variable_type(src, i, NULL, NULL)); } } @@ -353,7 +361,7 @@ int array_fill(struct page *dst, int dst_i, int n, union vm_value v) return n; } -void array_pushback(struct page **dst, union vm_value v, int data_type, int struct_type) +void array_pushback(struct page **dst, union vm_value v, enum ain_data_type data_type, int struct_type) { if (*dst) { if ((*dst)->type != ARRAY_PAGE) @@ -415,7 +423,7 @@ bool array_erase(struct page **_page, int i) return true; } -void array_insert(struct page **_page, int i, union vm_value v, int data_type, int struct_type) +void array_insert(struct page **_page, int i, union vm_value v, enum ain_data_type data_type, int struct_type) { struct page *page = *_page; if (!page) { diff --git a/page.h b/page.h index 474c803..591f43f 100644 --- a/page.h +++ b/page.h @@ -74,7 +74,7 @@ static inline void page_set(int pageno, int varno, union vm_value v) // variables union vm_value variable_initval(enum ain_data_type type); void variable_fini(union vm_value v, enum ain_data_type type); -enum ain_data_type variable_type(struct page *page, int varno, int *struct_type); +enum ain_data_type variable_type(struct page *page, int varno, int *struct_type, int *array_rank); // pages struct page *alloc_page(enum page_type type, int type_index, int nr_vars); @@ -89,15 +89,15 @@ void create_struct(int no, union vm_value *var); // arrays enum ain_data_type array_type(enum ain_data_type type); -struct page *alloc_array(int rank, union vm_value *dimensions, int data_type, int struct_type, bool init_structs); -struct page *realloc_array(struct page *src, int rank, union vm_value *dimensions, int data_type, int struct_type, bool init_structs); +struct page *alloc_array(int rank, union vm_value *dimensions, enum ain_data_type data_type, int struct_type, bool init_structs); +struct page *realloc_array(struct page *src, int rank, union vm_value *dimensions, enum ain_data_type data_type, int struct_type, bool init_structs); int array_numof(struct page *page, int rank); void array_copy(struct page *dst, int dst_i, struct page *src, int src_i, int n); int array_fill(struct page *dst, int dst_i, int n, union vm_value v); -void array_pushback(struct page **dst, union vm_value v, int data_type, int struct_type); +void array_pushback(struct page **dst, union vm_value v, enum ain_data_type data_type, int struct_type); void array_popback(struct page **dst); bool array_erase(struct page **page, int i); -void array_insert(struct page **_page, int i, union vm_value v, int data_type, int struct_type); +void array_insert(struct page **_page, int i, union vm_value v, enum ain_data_type data_type, int struct_type); void array_sort(struct page *page, int compare_fno); int array_find(struct page *page, int start, int end, union vm_value v, int compare_fno); void array_reverse(struct page *page); diff --git a/savedata.c b/savedata.c index a51cdc4..9d19b50 100644 --- a/savedata.c +++ b/savedata.c @@ -24,9 +24,12 @@ #include "vm.h" #include "cJSON.h" +static int current_global; + #define invalid_save_data(msg, data) { \ char *str = data ? cJSON_Print(data) : strdup("NULL"); \ - WARNING("Invalid save data: " msg ": %s", data); \ + if (!str) str = strdup("PRINTING FAILED"); \ + WARNING("Invalid save data (%d): " msg ": %s", current_global, data); \ free(str); \ } @@ -49,7 +52,7 @@ static cJSON *page_to_json(int index) cJSON *values = cJSON_CreateArray(); for (int i = 0; i < page->nr_vars; i++) { - cJSON_AddItemToArray(values, vm_value_to_json(variable_type(page, i, NULL), page->values[i])); + cJSON_AddItemToArray(values, vm_value_to_json(variable_type(page, i, NULL, NULL), page->values[i])); } return values; } @@ -173,26 +176,15 @@ int save_group(const char *keyname, const char *filename, const char *group_name return write_save_data(&data, filename); } -static union vm_value json_to_vm_value(enum ain_data_type type, enum ain_data_type struct_type, cJSON *json); +static union vm_value json_to_vm_value(enum ain_data_type type, enum ain_data_type struct_type, int array_rank, cJSON *json); -int get_json_array_rank(cJSON *json, union vm_value **dims) +void get_array_dims(cJSON *json, int rank, union vm_value *dims) { - // count rank - int rank = 1; cJSON *array = json; - while (cJSON_GetArraySize(array) > 0 && !cJSON_IsArray((array = cJSON_GetArrayItem(array, 0)))) { - rank++; - } - - // count dims - array = json; - *dims = xmalloc(sizeof(union vm_value) * rank); for (int i = 0; i < rank; i++) { - (*dims)[i].i = cJSON_GetArraySize(array); + dims[i].i = cJSON_GetArraySize(array); array = cJSON_GetArrayItem(array, 0); } - - return rank; } static void load_page(struct page *page, cJSON *vars) @@ -200,18 +192,19 @@ static void load_page(struct page *page, cJSON *vars) int i = 0; cJSON *v; cJSON_ArrayForEach(v, vars) { - int struct_type; - enum ain_data_type data_type = variable_type(page, i, &struct_type); - page->values[i] = json_to_vm_value(data_type, struct_type, v); + int struct_type, array_rank; + enum ain_data_type data_type = variable_type(page, i, &struct_type, &array_rank); + page->values[i] = json_to_vm_value(data_type, struct_type, array_rank, v); i++; } } -static union vm_value json_to_vm_value(enum ain_data_type type, enum ain_data_type struct_type, cJSON *json) +static union vm_value json_to_vm_value(enum ain_data_type type, enum ain_data_type struct_type, int array_rank, cJSON *json) { char *str; - int slot, rank; + int slot; union vm_value *dims; + struct page *page; switch (type) { case AIN_INT: case AIN_BOOL: @@ -265,8 +258,10 @@ static union vm_value json_to_vm_value(enum ain_data_type type, enum ain_data_ty heap[slot].page = NULL; return vm_int(slot); } - rank = get_json_array_rank(json, &dims); - heap[slot].page = alloc_array(rank, dims, array_type(type), struct_type, false); + dims = xmalloc(sizeof(union vm_value) * array_rank); + get_array_dims(json, array_rank, dims); + page = alloc_array(array_rank, dims, type, struct_type, false); + heap[slot].page = page; free(dims); load_page(heap[slot].page, json); return vm_int(slot); @@ -356,7 +351,8 @@ int load_globals(const char *keyname, const char *filename, const char *group_na invalid_save_data("Invalid global index", index); goto cleanup; } - global_set(i, json_to_vm_value(ain->globals[i].data_type, ain->globals[i].struct_type, value)); + current_global = i; + global_set(i, json_to_vm_value(ain->globals[i].data_type, ain->globals[i].struct_type, ain->globals[i].array_dimensions, value)); if (n) (*n)++; } diff --git a/vm.c b/vm.c index ad0fb0a..a672c6a 100644 --- a/vm.c +++ b/vm.c @@ -270,6 +270,8 @@ static union vm_value *stack_pop_var(void) { int32_t page_index = stack_pop().i; int32_t heap_index = stack_pop().i; + if (heap_index < 0 || (size_t)heap_index >= heap_size) + VM_ERROR("Out of bounds heap index: %d/%d", heap_index, page_index); if (!heap[heap_index].page || page_index >= heap[heap_index].page->nr_vars) VM_ERROR("Out of bounds page index: %d/%d", heap_index, page_index); return &heap[heap_index].page->values[page_index]; @@ -460,15 +462,35 @@ static void function_return(void) call_stack_ptr--; } +enum syscall_code { + SYS_EXIT = 0x00, + SYS_GLOBAL_SAVE = 0x01, + SYS_GLOBAL_LOAD = 0x02, + SYS_LOCK_PEEK = 0x03, + SYS_UNLOCK_PEEK = 0x04, + SYS_OUTPUT = 0x06, + SYS_EXISTS_FILE = 0x0A, + SYS_GET_SAVE_FOLDER_NAME = 0x0C, + SYS_GET_TIME = 0x0D, + SYS_ERROR = 0x0F, + SYS_EXISTS_SAVE_FILE = 0x10, + SYS_IS_DEBUG_MODE = 0x11, + SYS_GET_FUNC_STACK_NAME = 0x13, + SYS_PEEK = 0x14, + SYS_SLEEP = 0x15, + SYS_GROUP_SAVE = 0x18, + SYS_GROUP_LOAD = 0x19 +}; + static void system_call(int32_t code) { char *utf; struct string *str; switch (code) { - case 0x0: // system.Exit(int nResult) + case SYS_EXIT: // system.Exit(int nResult) vm_exit(stack_pop().i); break; - case 0x1: { // system.GlobalSave(string szKeyName, string szFileName) + case SYS_GLOBAL_SAVE: { // system.GlobalSave(string szKeyName, string szFileName) int filename = stack_pop().i; int keyname = stack_pop().i; stack_push(save_globals(heap[keyname].s->text, heap[filename].s->text)); @@ -476,7 +498,7 @@ static void system_call(int32_t code) heap_unref(keyname); break; } - case 0x2: { // system.GlobalLoad(string szKeyName, string szFileName) + case SYS_GLOBAL_LOAD: { // system.GlobalLoad(string szKeyName, string szFileName) int filename = stack_pop().i; int keyname = stack_pop().i; stack_push(load_globals(heap[keyname].s->text, heap[filename].s->text, NULL, NULL)); @@ -484,18 +506,18 @@ static void system_call(int32_t code) heap_unref(keyname); break; } - case 0x3: // system.LockPeek(void) - case 0x4: // system.UnlockPeek(void) + case SYS_LOCK_PEEK: // system.LockPeek(void) + case SYS_UNLOCK_PEEK: // system.UnlockPeek(void) stack_push(1); break; - case 0x6: // system.Output(string szText) + case SYS_OUTPUT: // system.Output(string szText) str = stack_peek_string(0); utf = sjis2utf(str->text, str->size); sys_message("%s", utf); free(utf); // XXX: caller S_POPs break; - case 0xA: { // system.ExistsFile(string szFileName) + case SYS_EXISTS_FILE: { // system.ExistsFile(string szFileName) int str = stack_pop().i; char *path = unix_path(heap[str].s->text); stack_push(file_exists(path)); @@ -503,23 +525,23 @@ static void system_call(int32_t code) free(path); break; } - case 0xC: // system.GetSaveFolderName(void) + case SYS_GET_SAVE_FOLDER_NAME: // system.GetSaveFolderName(void) if (config.save_dir) stack_push_string(make_string(config.save_dir, strlen(config.save_dir))); else stack_push_string(string_ref(&EMPTY_STRING)); break; - case 0xD: // system.GetTime(void) + case SYS_GET_TIME: // system.GetTime(void) stack_push(vm_time()); break; - case 0xF: // system.Error(string szText) + case SYS_ERROR: // system.Error(string szText) str = stack_peek_string(0); utf = sjis2utf(str->text, str->size); sys_warning("*GAME ERROR*: %s\n", utf); free(utf); // XXX: caller S_POPs break; - case 0x10: { + case SYS_EXISTS_SAVE_FILE: { int slot = stack_pop().i; struct string *name = heap[slot].s; size_t dir_len = strlen(config.save_dir); @@ -532,14 +554,13 @@ static void system_call(int32_t code) stack_push(file_exists(path)); heap_unref(slot); - NOTICE("-----PATH=%s", path); free(path); break; } - case 0x11: // system.IsDebugMode(void) + case SYS_IS_DEBUG_MODE: // system.IsDebugMode(void) stack_push(0); break; - case 0x13: { // system.GetFuncStackName(int nIndex) + case SYS_GET_FUNC_STACK_NAME: { // system.GetFuncStackName(int nIndex) int i = call_stack_ptr - (1 + stack_pop().i); if (i < 0 || i >= call_stack_ptr) { const char *msg = "Invalid stack index"; @@ -551,12 +572,12 @@ static void system_call(int32_t code) stack_push_string(make_string(fun->name, strlen(fun->name))); break; } - case 0x14: // system.Peek(void) + case SYS_PEEK: // system.Peek(void) break; - case 0x15: // system.Sleep(int nSleep) + case SYS_SLEEP: // system.Sleep(int nSleep) stack_pop(); break; - case 0x18: { // system.GroupSave(string szKeyName, string szFileName, string szGroupName, ref int nNumofLoad) + case SYS_GROUP_SAVE: { // system.GroupSave(string szKeyName, string szFileName, string szGroupName, ref int nNumofLoad) union vm_value *n = stack_pop_var(); int groupname = stack_pop().i; int filename = stack_pop().i; @@ -567,7 +588,7 @@ static void system_call(int32_t code) heap_unref(keyname); break; } - case 0x19: { // system.GroupLoad(string szKeyName, string szFileName, string szGroupName, ref int nNumofLoad) + case SYS_GROUP_LOAD: { // system.GroupLoad(string szKeyName, string szFileName, string szGroupName, ref int nNumofLoad) union vm_value *n = stack_pop_var(); int groupname = stack_pop().i; int filename = stack_pop().i; @@ -1451,7 +1472,7 @@ static void execute_instruction(enum opcode opcode) int varno = stack_peek(rank).i; int pageno = stack_peek(rank+1).i; int array = heap[pageno].page->values[varno].i; - enum ain_data_type data_type = variable_type(heap[pageno].page, varno, &struct_type); + enum ain_data_type data_type = variable_type(heap[pageno].page, varno, &struct_type, NULL); heap_set_page(array, alloc_array(rank, stack_peek_ptr(rank-1), data_type, struct_type, true)); stack_ptr -= rank + 2; break; @@ -1462,7 +1483,7 @@ static void execute_instruction(enum opcode opcode) int varno = stack_peek(rank).i; int pageno = stack_peek(rank+1).i; int array = heap[pageno].page->values[varno].i; - enum ain_data_type data_type = variable_type(heap[pageno].page, varno, &struct_type); + enum ain_data_type data_type = variable_type(heap[pageno].page, varno, &struct_type, NULL); heap_set_page(array, realloc_array(heap[array].page, rank, stack_peek_ptr(rank-1), data_type, struct_type, true)); stack_ptr -= rank + 2; break; @@ -1513,7 +1534,7 @@ static void execute_instruction(enum opcode opcode) int varno = stack_pop().i; int pageno = stack_pop().i; int array = heap[pageno].page->values[varno].i; - enum ain_data_type data_type = variable_type(heap[pageno].page, varno, &struct_type); + enum ain_data_type data_type = variable_type(heap[pageno].page, varno, &struct_type, NULL); array_pushback(&heap[array].page, val, data_type, struct_type); break; } @@ -1539,7 +1560,7 @@ static void execute_instruction(enum opcode opcode) int varno = stack_pop().i; int pageno = stack_pop().i; int array = heap[pageno].page->values[varno].i; - enum ain_data_type data_type = variable_type(heap[pageno].page, varno, &struct_type); + enum ain_data_type data_type = variable_type(heap[pageno].page, varno, &struct_type, NULL); array_insert(&heap[array].page, i, val, data_type, struct_type); break; }