aindump/ainedit: initial ain v14 support

Support for Evenicle 2 and Haha Ranman.

There are a few changes in v14:
* a number of new instructions (semantics yet unknown)
* HLL function arguments and return values can now be complex types
  (e.g. arrays, enums)
* support for nested arrays (this isn't necessarily new, but it doesn't
  occur in Rance X at all)
This commit is contained in:
Nunuhara Cabbage
2020-05-17 13:21:37 -07:00
parent 43818e636a
commit b617449178
13 changed files with 302 additions and 106 deletions
+20 -7
View File
@@ -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 */
+36
View File
@@ -0,0 +1,36 @@
/* 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/>.
*/
#ifndef SYSTEM4_HASHTABLE_H
#define SYSTEM4_HASHTABLE_H
#include <stddef.h>
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 */
+11
View File
@@ -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
};
+73 -70
View File
@@ -25,10 +25,10 @@
#include <string.h>
#include <zlib.h>
#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);
}
+7 -7
View File
@@ -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");
+111
View File
@@ -0,0 +1,111 @@
/* 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 <stdlib.h>
#include <string.h>
#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);
}
+11
View File
@@ -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)
+1
View File
@@ -9,6 +9,7 @@ system4 = ['afa.c',
'ex.c',
'file.c',
'fnl.c',
'hashtable.c',
'instructions.c',
'pms.c',
'qnt.c',
+1 -1
View File
@@ -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.
+3 -3
View File
@@ -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);
}
+4 -2
View File
@@ -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);
+8 -2
View File
@@ -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;
+16 -14
View File
@@ -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);
}
}
}
}