diff --git a/include/system4/ain.h b/include/system4/ain.h index 0084006..d68f0eb 100644 --- a/include/system4/ain.h +++ b/include/system4/ain.h @@ -74,11 +74,13 @@ enum ain_data_type { AIN_REF_ARRAY = 80, AIN_ITERATOR = 82, // array iterator AIN_ENUM1 = 86, // return value of EnumType::Parse; has type 91 in array type + AIN_UNKNOWN_TYPE_87 = 87, AIN_IFACE = 89, // 2 values: [0] = struct page, [1] = vtable offset to inteface methods AIN_ENUM2 = 91, // used as array type of type 86; has enum type in struct type AIN_ENUM3 = 92, // used as argument type, and array type in EnumType::GetList; has enum type in struct type AIN_REF_ENUM = 93, AIN_UNKNOWN_TYPE_95 = 95, // function? + AIN_UNKNOWN_TYPE_100 = 100, }; #define AIN_ARRAY_TYPE \ @@ -186,12 +188,12 @@ struct ain_struct { struct ain_hll_argument { char *name; - int32_t data_type; + struct ain_type type; }; struct ain_hll_function { char *name; - int32_t data_type; + struct ain_type return_type; int32_t nr_arguments; struct ain_hll_argument *arguments; }; @@ -234,9 +236,6 @@ struct ain_enum { char **symbols; }; -struct kh_func_ht_s; -struct kh_struct_ht_s; - struct ain_section { uint32_t addr; uint32_t size; @@ -307,8 +306,8 @@ struct ain { struct ain_section OBJG; struct ain_section ENUM; - struct kh_func_ht_s *_func_ht; - struct kh_struct_ht_s *_struct_ht; + struct hash_table *_func_ht; + struct hash_table *_struct_ht; }; const char *ain_strerror(int error); @@ -338,4 +337,18 @@ void ain_free_delegates(struct ain *ain); void ain_free_global_groups(struct ain *ain); void ain_free_enums(struct ain *ain); +static inline bool ain_array_data_type(int32_t type) +{ + switch (type) { + case AIN_ARRAY: + case AIN_REF_ARRAY: + case AIN_ITERATOR: + case AIN_ENUM1: + case AIN_UNKNOWN_TYPE_87: + return true; + default: + return false; + } +} + #endif /* SYSTEM4_AIN_H */ diff --git a/include/system4/hashtable.h b/include/system4/hashtable.h new file mode 100644 index 0000000..a638009 --- /dev/null +++ b/include/system4/hashtable.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2019 Nunuhara Cabbage + * + * 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 . + */ + +#ifndef SYSTEM4_HASHTABLE_H +#define SYSTEM4_HASHTABLE_H + +#include + +struct ht_slot { + const char *key; + void *value; +}; + +struct hash_table; + +struct hash_table *ht_create(size_t nr_buckets); +void ht_free(struct hash_table *ht); + +void *ht_get(struct hash_table *ht, const char *key); +struct ht_slot *ht_put(struct hash_table *ht, const char *key); +void ht_foreach_value(struct hash_table *ht, void(*fun)(void*)); + +#endif /* SYSTEM4_HASHTABLE_H */ diff --git a/include/system4/instructions.h b/include/system4/instructions.h index f251667..8c99e11 100644 --- a/include/system4/instructions.h +++ b/include/system4/instructions.h @@ -332,6 +332,17 @@ enum opcode OP_0X103 = 0x103, OP_0X104 = 0x104, OP_0X105 = 0x105, + OP_0X106 = 0x106, + OP_0X107 = 0x107, // unused + OP_0X108 = 0x108, // unused + OP_0X109 = 0x109, // unused + OP_0X10A = 0x10A, + OP_0X10B = 0x10B, + OP_0X10C = 0x10C, + OP_0X10D = 0x10D, + OP_0X10E = 0x10E, + OP_0X10F = 0x10F, + OP_0X110 = 0x110, NR_OPCODES }; diff --git a/src/ain.c b/src/ain.c index 550342b..26f6d2d 100644 --- a/src/ain.c +++ b/src/ain.c @@ -25,10 +25,10 @@ #include #include -#include "khash.h" #include "little_endian.h" #include "system4.h" #include "system4/ain.h" +#include "system4/hashtable.h" #include "system4/instructions.h" #include "system4/string.h" #include "system4/utfsjis.h" @@ -39,45 +39,37 @@ struct func_list { }; #define func_list_size(nr_slots) (sizeof(struct func_list) + sizeof(struct ain_function*)*(nr_slots)) -KHASH_MAP_INIT_STR(func_ht, struct func_list*); -KHASH_MAP_INIT_STR(struct_ht, struct ain_struct*); - static void init_func_ht(struct ain *ain) { + ain->_func_ht = ht_create(1024); for (int i = 0; i < ain->nr_functions; i++) { - int ret; - khiter_t k = kh_put(func_ht, ain->_func_ht, ain->functions[i].name, &ret); - if (!ret) { - // entry with this name already exists: add to list - struct func_list *list = kh_value(ain->_func_ht, k); + struct ht_slot *kv = ht_put(ain->_func_ht, ain->functions[i].name); + if (kv->value) { + // entry with this name already exists; add to list + struct func_list *list = kv->value; list = xrealloc(list, func_list_size(list->nr_slots+1)); list->slots[list->nr_slots] = &ain->functions[i]; list->nr_slots++; - kh_value(ain->_func_ht, k) = list; - } else if (ret == 1) { + kv->value = list; + } else { // empty bucket: create list struct func_list *list = xmalloc(func_list_size(1)); list->nr_slots = 1; list->slots[0] = &ain->functions[i]; - kh_value(ain->_func_ht, k) = list; - } else { - ERROR("Failed to insert function into hash table (%d)", ret); + kv->value = list; } } } static void init_struct_ht(struct ain *ain) { + ain->_struct_ht = ht_create(1024); for (int i = 0; i < ain->nr_structures; i++) { - int ret; - khiter_t k = kh_put(struct_ht, ain->_struct_ht, ain->structures[i].name, &ret); - if (!ret) { + struct ht_slot *kv = ht_put(ain->_struct_ht, ain->structures[i].name); + if (kv->value) { ERROR("Duplicate structure names: '%s'", ain->structures[i].name); - } else if (ret == 1) { - kh_value(ain->_struct_ht, k) = &ain->structures[i]; - } else { - ERROR("Failed to insert struct into hash table (%d)", ret); } + kv->value = &ain->structures[i]; } } @@ -146,11 +138,7 @@ static void init_member_functions(struct ain *ain) static struct func_list *get_function(struct ain *ain, const char *name) { - int ret; - khiter_t k = kh_put(func_ht, ain->_func_ht, name, &ret); - if (ret) - return NULL; - return kh_value(ain->_func_ht, k); + return ht_get(ain->_func_ht, name); } struct ain_function *ain_get_function(struct ain *ain, char *name) @@ -192,10 +180,7 @@ err: struct ain_struct *ain_get_struct(struct ain *ain, char *name) { - khiter_t k = kh_get(struct_ht, ain->_struct_ht, name); - if (k == kh_end(ain->_struct_ht)) - return NULL; - return kh_value(ain->_struct_ht, k); + return ht_get(ain->_struct_ht, name); } static const char *errtab[AIN_MAX_ERROR] = { @@ -321,25 +306,25 @@ char *ain_strtype_d(struct ain *ain, struct ain_type *v) case AIN_ITERATOR: return container_type_string(ain, v); case AIN_ENUM1: - if (!v->array_type || v->array_type->struc == -1 || !ain) + if (!v->array_type || v->array_type->struc == -1 || !ain || v->array_type->struc >= ain->nr_enums) return strdup("enum"); - //return strdup(ain->enums[v->array_type->struc]); return type_sprintf("%s#86", ain->enums[v->array_type->struc].name); + case AIN_UNKNOWN_TYPE_87: return strdup("type_87"); case AIN_IFACE: if (v->struc == -1 || !ain) return strdup("interface"); return strdup(ain->structures[v->struc].name); case AIN_ENUM2: case AIN_ENUM3: - if (v->struc == -1 || !ain) + if (v->struc == -1 || !ain || v->struc >= ain->nr_enums) return strdup("enum"); - //return strdup(ain->enums[v->struc]); return type_sprintf("%s#%d", ain->enums[v->struc].name, v->data); case AIN_REF_ENUM: - if (v->struc == -1 || !ain) + if (v->struc == -1 || !ain || v->struc >= ain->nr_enums) return strdup("enum"); return type_sprintf("ref %s", ain->enums[v->struc].name); case AIN_UNKNOWN_TYPE_95: return strdup("type_95"); + case AIN_UNKNOWN_TYPE_100: return strdup("type_100"); default: WARNING("Unknown type: %d", v->data); return type_sprintf("unknown_type_%d", v->data); @@ -379,6 +364,7 @@ struct ain_reader { size_t size; size_t index; struct ain_section *section; + struct ain *ain; }; static int32_t read_int32(struct ain_reader *r) @@ -458,25 +444,16 @@ static struct string **read_msg1_strings(struct ain_reader *r, int count) return strings; } -static struct ain_type *read_array_type(struct ain_reader *r) +static void read_variable_type(struct ain_reader *r, struct ain_type *t); + +static struct ain_type *read_array_type(struct ain_reader *r, int rank) { - int32_t data_type = read_int32(r); - int32_t struct_type = read_int32(r); - int32_t array_rank = read_int32(r); + if (rank < 0) + ERROR("Invalid array rank: %d", rank); - if (array_rank < 0) - ERROR("Invalid array rank: %d", array_rank); - - struct ain_type *type = xcalloc(array_rank+1, sizeof(struct ain_type)); - type[0].data = data_type; - type[0].struc = struct_type; - type[0].rank = array_rank; - - for (int i = 0; i < array_rank; i++) { - type[i+1].data = read_int32(r); - type[i+1].struc = read_int32(r); - type[i+1].rank = read_int32(r); - type[i].array_type = type + i + 1; + struct ain_type *type = xcalloc(rank, sizeof(struct ain_type)); + for (int i = 0; i < rank; i++) { + read_variable_type(r, type+i); } return type; @@ -506,8 +483,8 @@ static void read_variable_type(struct ain_reader *r, struct ain_type *t) t->struc = read_int32(r); t->rank = read_int32(r); - if (t->data == AIN_ARRAY || t->data == AIN_REF_ARRAY || t->data == AIN_ITERATOR || t->data == AIN_ENUM1) - t->array_type = read_array_type(r); + if (ain_array_data_type(t->data)) + t->array_type = read_array_type(r, t->rank); } static struct ain_variable *read_variables(struct ain_reader *r, int count, struct ain *ain, enum ain_variable_type var_type) @@ -626,7 +603,13 @@ static struct ain_hll_argument *read_hll_arguments(struct ain_reader *r, int cou struct ain_hll_argument *arguments = calloc(count, sizeof(struct ain_hll_argument)); for (int i = 0; i < count; i++) { arguments[i].name = read_string(r); - arguments[i].data_type = read_int32(r); + if (r->ain->version >= 14) { + read_variable_type(r, &arguments[i].type); + } else { + arguments[i].type.data = read_int32(r); + arguments[i].type.struc = -1; + arguments[i].type.rank = 0; + } } return arguments; } @@ -636,8 +619,16 @@ static struct ain_hll_function *read_hll_functions(struct ain_reader *r, int cou struct ain_hll_function *functions = calloc(count, sizeof(struct ain_hll_function)); for (int i = 0; i < count; i++) { functions[i].name = read_string(r); - functions[i].data_type = read_int32(r); + if (r->ain->version >= 14) { + read_variable_type(r, &functions[i].return_type); + } else { + functions[i].return_type.data = read_int32(r); + functions[i].return_type.struc = -1; + functions[i].return_type.rank = 0; + } functions[i].nr_arguments = read_int32(r); + if (functions[i].nr_arguments > 100 || functions[i].nr_arguments < 0) + ERROR("TOO MANY ARGUMENTS (AT 0x%x)", r->index); functions[i].arguments = read_hll_arguments(r, functions[i].nr_arguments); } return functions; @@ -710,8 +701,10 @@ struct ain_enum *read_enums(struct ain_reader *r, int count, struct ain *ain) struct ain_enum *enums = xcalloc(count, sizeof(struct ain_enum)); for (int i = 0; i < count; i++) { + enums[i].name = names[i]; + char buf[1024] = { [1023] = '\0' }; - snprintf(buf, 1023, "%s@String", names[i]); + snprintf(buf, 1023, ain->version < 14 ? "%s@String" : "%s::ToString", names[i]); struct func_list *funs = get_function(ain, buf); if (!funs || funs->nr_slots != 1) { @@ -739,7 +732,6 @@ struct ain_enum *read_enums(struct ain_reader *r, int count, struct ain *ain) enums[i].nr_symbols = j + 1; j++; }); - enums[i].name = names[i]; } free(names); @@ -1027,14 +1019,13 @@ struct ain *ain_open(const char *path, int *error) goto err; // read data into ain struct + ain = calloc(1, sizeof(struct ain)); struct ain_reader r = { .buf = buf, .index = 0, - .size = len + .size = len, + .ain = ain }; - ain = calloc(1, sizeof(struct ain)); - ain->_func_ht = kh_init(func_ht); - ain->_struct_ht = kh_init(struct_ht); while (read_tag(&r, ain)); if (!ain->version) { *error = AIN_INVALID; @@ -1052,12 +1043,23 @@ err: return NULL; } +static void ain_free_type(struct ain_type *type) +{ + if (!type->array_type) + return; + + for (int i = 0; i < type->rank; i++) { + ain_free_type(&type->array_type[i]); + } + free(type->array_type); +} + static void ain_free_variables(struct ain_variable *vars, int nr_vars) { for (int i = 0; i < nr_vars; i++) { free(vars[i].name); free(vars[i].name2); - free(vars[i].type.array_type); + ain_free_type(&vars[i].type); if (vars[i].has_initval && vars[i].type.data == AIN_STRING) free(vars[i].initval.s); } @@ -1068,7 +1070,7 @@ static void _ain_free_function_types(struct ain_function_type *funs, int n) { for (int i = 0; i < n; i++) { free(funs[i].name); - free(funs[i].return_type.array_type); + ain_free_type(&funs[i].return_type); ain_free_variables(funs[i].variables, funs[i].nr_variables); } free(funs); @@ -1094,7 +1096,7 @@ void ain_free_functions(struct ain *ain) { for (int f = 0; f < ain->nr_functions; f++) { free(ain->functions[f].name); - free(ain->functions[f].return_type.array_type); + ain_free_type(&ain->functions[f].return_type); ain_free_variables(ain->functions[f].vars, ain->functions[f].nr_vars); } free(ain->functions); @@ -1141,8 +1143,10 @@ void ain_free_libraries(struct ain *ain) free(ain->libraries[lib].name); for (int f = 0; f < ain->libraries[lib].nr_functions; f++) { free(ain->libraries[lib].functions[f].name); + ain_free_type(&ain->libraries[lib].functions[f].return_type); for (int a = 0; a < ain->libraries[lib].functions[f].nr_arguments; a++) { free(ain->libraries[lib].functions[f].arguments[a].name); + ain_free_type(&ain->libraries[lib].functions[f].arguments[a].type); } free(ain->libraries[lib].functions[f].arguments); } @@ -1213,6 +1217,10 @@ void ain_free(struct ain *ain) { free(ain->code); + ht_foreach_value(ain->_func_ht, free); + ht_free(ain->_func_ht); + ht_free(ain->_struct_ht); + ain_free_functions(ain); ain_free_globals(ain); ain_free_initvals(ain); @@ -1227,10 +1235,5 @@ void ain_free(struct ain *ain) ain_free_global_groups(ain); ain_free_enums(ain); - struct func_list *list; - kh_foreach_value(ain->_func_ht, list, free(list)); - kh_destroy(func_ht, ain->_func_ht); - kh_destroy(struct_ht, ain->_struct_ht); - free(ain); } diff --git a/src/ffi.c b/src/ffi.c index c22c5ef..60b780e 100644 --- a/src/ffi.c +++ b/src/ffi.c @@ -57,7 +57,7 @@ void hll_call(int libno, int fno) void *args[HLL_MAX_ARGS]; void *ptrs[HLL_MAX_ARGS]; for (int i = f->nr_arguments - 1; i >= 0; i--) { - switch (f->arguments[i].data_type) { + switch (f->arguments[i].type.data) { case AIN_REF_INT: case AIN_REF_LONG_INT: case AIN_REF_BOOL: @@ -103,7 +103,7 @@ void hll_call(int libno, int fno) for (int i = 0, j = 0; i < f->nr_arguments; i++, j++) { // XXX: We don't increase the ref count when passing ref arguments to HLL // functions, so we need to avoid decreasing it via variable_fini - switch (f->arguments[i].data_type) { + switch (f->arguments[i].type.data) { case AIN_REF_INT: case AIN_REF_LONG_INT: case AIN_REF_BOOL: @@ -116,13 +116,13 @@ void hll_call(int libno, int fno) case AIN_REF_ARRAY_TYPE: break; default: - variable_fini(stack[stack_ptr+j], f->arguments[i].data_type); + variable_fini(stack[stack_ptr+j], f->arguments[i].type.data); break; } } - if (f->data_type != AIN_VOID) { - if (f->data_type == AIN_STRING) { + if (f->return_type.data != AIN_VOID) { + if (f->return_type.data == AIN_STRING) { int slot = heap_alloc_slot(VM_STRING); heap[slot].s = r.ref; } else { @@ -202,9 +202,9 @@ static void link_static_library_function(struct hll_function *dst, struct ain_hl dst->args = xcalloc(dst->nr_args, sizeof(ffi_type*)); for (unsigned int i = 0; i < dst->nr_args; i++) { - dst->args[i] = ain_to_ffi_type(src->arguments[i].data_type); + dst->args[i] = ain_to_ffi_type(src->arguments[i].type.data); } - dst->return_type = ain_to_ffi_type(src->data_type); + dst->return_type = ain_to_ffi_type(src->return_type.data); if (ffi_prep_cif(&dst->cif, FFI_DEFAULT_ABI, dst->nr_args, dst->return_type, dst->args) != FFI_OK) ERROR("Failed to link HLL function"); diff --git a/src/hashtable.c b/src/hashtable.c new file mode 100644 index 0000000..67be4da --- /dev/null +++ b/src/hashtable.c @@ -0,0 +1,111 @@ +/* Copyright (C) 2019 Nunuhara Cabbage + * + * 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 . + */ + +#include +#include +#include "system4.h" +#include "system4/hashtable.h" + +struct ht_bucket { + size_t nr_slots; + struct ht_slot slots[]; +}; + +struct hash_table { + size_t nr_buckets; + struct ht_bucket *buckets[]; +}; + +static unsigned long string_hash(const char *_str) +{ + const unsigned char *str = (const unsigned char*)_str; + unsigned long hash = 5381; + int c; + + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; +} + +struct hash_table *ht_create(size_t nr_buckets) +{ + struct hash_table *ht = xmalloc(sizeof(struct hash_table) + sizeof(struct ht_bucket*)*nr_buckets); + ht->nr_buckets = nr_buckets; + for (size_t i = 0; i < nr_buckets; i++) { + ht->buckets[i] = NULL; + } + return ht; +} + +void *ht_get(struct hash_table *ht, const char *key) +{ + unsigned long k = string_hash(key) & (ht->nr_buckets - 1); + if (!ht->buckets[k]) + return NULL; + for (size_t i = 0; i < ht->buckets[k]->nr_slots; i++) { + if (!strcmp(ht->buckets[k]->slots[i].key, key)) + return ht->buckets[k]->slots[i].value; + } + return NULL; +} + +struct ht_slot *ht_put(struct hash_table *ht, const char *key) +{ + unsigned long k = string_hash(key) & (ht->nr_buckets - 1); + + // init new bucket + if (!ht->buckets[k]) { + ht->buckets[k] = xmalloc(sizeof(struct ht_bucket) + sizeof(struct ht_slot)); + ht->buckets[k]->nr_slots = 1; + ht->buckets[k]->slots[0].key = key; + ht->buckets[k]->slots[0].value = NULL; + return &ht->buckets[k]->slots[0]; + } + + // search for key in bucket + for (size_t i = 0; i < ht->buckets[k]->nr_slots; i++) { + if (!strcmp(ht->buckets[k]->slots[i].key, key)) + return &ht->buckets[k]->slots[i]; + } + + // alloc new slot + size_t i = ht->buckets[k]->nr_slots; + ht->buckets[k] = xrealloc(ht->buckets[k], sizeof(struct ht_bucket) + sizeof(struct ht_slot)*(i+1)); + ht->buckets[k]->nr_slots = i+1; + ht->buckets[k]->slots[i].key = key; + ht->buckets[k]->slots[i].value = NULL; + return &ht->buckets[k]->slots[i]; +} + +void ht_foreach_value(struct hash_table *ht, void(*fun)(void*)) +{ + for (size_t i = 0; i < ht->nr_buckets; i++) { + if (!ht->buckets[i]) + continue; + for (size_t j = 0; j < ht->buckets[i]->nr_slots; j++) { + fun(ht->buckets[i]->slots[j].value); + } + } +} + +void ht_free(struct hash_table *ht) +{ + for (size_t i = 0; i < ht->nr_buckets; i++) { + free(ht->buckets[i]); + } + free(ht); +} diff --git a/src/instructions.c b/src/instructions.c index 017bf2c..68f3f61 100644 --- a/src/instructions.c +++ b/src/instructions.c @@ -377,6 +377,17 @@ struct instruction instructions[NR_OPCODES] = { TODO ( OP_0X103, 0 ), TODO ( OP_0X104, 0 ), TODO ( OP_0X105, 1, T_STRUCT ), + TODO ( OP_0X106, 1, T_INT ), + TODO ( OP_0X107, 0 ), + TODO ( OP_0X108, 0 ), + TODO ( OP_0X109, 0 ), + TODO ( OP_0X10A, 1, T_INT ), + TODO ( OP_0X10B, 2, T_INT, T_INT ), + TODO ( OP_0X10C, 1, T_INT ), + TODO ( OP_0X10D, 1, T_INT ), + TODO ( OP_0X10E, 1, T_INT ), + TODO ( OP_0X10F, 0 ), + TODO ( OP_0X110, 1, T_INT ), }; void initialize_instructions(void) diff --git a/src/meson.build b/src/meson.build index 9b034f7..563e14c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -9,6 +9,7 @@ system4 = ['afa.c', 'ex.c', 'file.c', 'fnl.c', + 'hashtable.c', 'instructions.c', 'pms.c', 'qnt.c', diff --git a/src/tools/README.md b/src/tools/README.md index fbcb7c2..ad50d28 100644 --- a/src/tools/README.md +++ b/src/tools/README.md @@ -7,7 +7,7 @@ used in AliceSoft games. The currently included tools are: * aindump - used to extract information from .ain files (code, text, etc.) * ainedit - used to reinsert information back into an .ain file * exdump - used to extract information from .ex files (static data) -* exbuild - used to rebuild an .ex file dumpbed by exdump +* exbuild - used to rebuild an .ex file dumped by exdump More tools are planned for future releases. diff --git a/src/tools/aindump/aindump.c b/src/tools/aindump/aindump.c index d838b67..d9ddb7f 100644 --- a/src/tools/aindump/aindump.c +++ b/src/tools/aindump/aindump.c @@ -323,17 +323,17 @@ static void ain_dump_libraries(FILE *out, struct ain *ain) fprintf(out, " ---\n"); for (int j = 0; j < ain->libraries[i].nr_functions; j++) { struct ain_hll_function *f = &ain->libraries[i].functions[j]; - print_sjis(out, ain_strtype(ain, f->data_type, -1)); + print_sjis(out, ain_strtype(ain, f->return_type.data, f->return_type.struc)); fputc(' ', out); print_sjis(out, f->name); fputc('(', out); for (int k = 0; k < f->nr_arguments; k++) { struct ain_hll_argument *a = &f->arguments[k]; - if (a->data_type == AIN_VOID) + if (a->type.data == AIN_VOID) continue; if (k > 0) fprintf(out, ", "); - print_sjis(out, ain_strtype(ain, a->data_type, -1)); + print_sjis(out, ain_strtype(ain, a->type.data, a->type.struc)); fputc(' ', out); print_sjis(out, a->name); } diff --git a/src/tools/aindump/json.c b/src/tools/aindump/json.c index 22604c3..9de4789 100644 --- a/src/tools/aindump/json.c +++ b/src/tools/aindump/json.c @@ -141,13 +141,15 @@ static cJSON *ain_library_to_json(struct ain_library *lib) for (int i = 0; i < lib->nr_functions; i++) { cJSON *f = cJSON_CreateObject(); cJSON_AddStringToObject(f, "name", lib->functions[i].name); - cJSON_AddNumberToObject(f, "return-type", lib->functions[i].data_type); + cJSON_AddNumberToObject(f, "return-type", lib->functions[i].return_type.data); + // TODO: v14 has full variable type cJSON *args = cJSON_CreateArray(); for (int j = 0; j < lib->functions[i].nr_arguments; j++) { cJSON *arg = cJSON_CreateObject(); cJSON_AddStringToObject(arg, "name", lib->functions[i].arguments[j].name); - cJSON_AddNumberToObject(arg, "type", lib->functions[i].arguments[j].data_type); + cJSON_AddNumberToObject(arg, "type", lib->functions[i].arguments[j].type.data); + // TODO: v14 has full variable type cJSON_AddItemToArray(args, arg); } cJSON_AddItemToObject(f, "arguments", args); diff --git a/src/tools/ainedit/json.c b/src/tools/ainedit/json.c index 299feaf..6863d35 100644 --- a/src/tools/ainedit/json.c +++ b/src/tools/ainedit/json.c @@ -272,14 +272,20 @@ static void read_library_declaration(cJSON *decl, struct ain_library *dst) struct ain_hll_function *funs = xcalloc(cJSON_GetArraySize(jfuns), sizeof(struct ain_hll_function)); cJSON_ArrayForEachIndex(i, f, jfuns) { funs[i].name = cJSON_GetObjectString_NonNull(f, "name"); - funs[i].data_type = cJSON_GetObjectInteger_NonNull(f, "return-type"); + funs[i].return_type.data = cJSON_GetObjectInteger_NonNull(f, "return-type"); + // TODO: v14 has full variable type + funs[i].return_type.struc = -1; + funs[i].return_type.rank = 0; int j; cJSON *arg, *jargs = cJSON_GetObjectArray_NonNull(f, "arguments"); struct ain_hll_argument *args = xcalloc(cJSON_GetArraySize(jargs), sizeof(struct ain_hll_argument)); cJSON_ArrayForEachIndex(j, arg, jargs) { args[j].name = cJSON_GetObjectString_NonNull(arg, "name"); - args[j].data_type = cJSON_GetObjectInteger_NonNull(arg, "type"); + args[j].type.data = cJSON_GetObjectInteger_NonNull(arg, "type"); + // TODO: v14 has full variable type + args[j].type.struc = -1; + args[j].type.rank = 0; } funs[i].nr_arguments = j; funs[i].arguments = args; diff --git a/src/tools/ainedit/repack.c b/src/tools/ainedit/repack.c index d9021ec..6da645d 100644 --- a/src/tools/ainedit/repack.c +++ b/src/tools/ainedit/repack.c @@ -76,23 +76,17 @@ static void write_header(struct ain_buffer *out, const char *s) write_bytes(out, (const uint8_t*)s, 4); } -static void write_array_type(struct ain_buffer *out, possibly_unused struct ain *ain, struct ain_type *t) -{ - for (int i = 0; i < t[0].rank+1; i++) { - write_int32(out, t[i].data); - write_int32(out, t[i].struc); - write_int32(out, t[i].rank); - } -} - static void write_variable_type(struct ain_buffer *out, struct ain *ain, struct ain_type *t) { write_int32(out, t->data); write_int32(out, t->struc); write_int32(out, t->rank); - if (t->data == AIN_ARRAY || t->data == AIN_REF_ARRAY || t->data == AIN_ITERATOR || t->data == AIN_ENUM1) - write_array_type(out, ain, t->array_type); + if (ain_array_data_type(t->data)) { + for (int i = 0; i < t->rank; i++) { + write_variable_type(out, ain, &t->array_type[i]); + } + } } static void write_return_type(struct ain_buffer *out, struct ain *ain, struct ain_type *t) @@ -184,17 +178,25 @@ static void write_structure(struct ain_buffer *out, struct ain *ain, struct ain_ } } -static void write_library(struct ain_buffer *out, possibly_unused struct ain *ain, struct ain_library *lib) +static void write_library(struct ain_buffer *out, struct ain *ain, struct ain_library *lib) { write_string(out, lib->name); write_int32(out, lib->nr_functions); for (int i = 0; i < lib->nr_functions; i++) { write_string(out, lib->functions[i].name); - write_int32(out, lib->functions[i].data_type); + if (ain->version >= 14) { + write_variable_type(out, ain, &lib->functions[i].return_type); + } else { + write_int32(out, lib->functions[i].return_type.data); + } write_int32(out, lib->functions[i].nr_arguments); for (int j = 0; j < lib->functions[i].nr_arguments; j++) { write_string(out, lib->functions[i].arguments[j].name); - write_int32(out, lib->functions[i].arguments[j].data_type); + if (ain->version >= 14) { + write_variable_type(out, ain, &lib->functions[i].arguments[j].type); + } else { + write_int32(out, lib->functions[i].arguments[j].type.data); + } } } }