mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-05 13:28:04 +03:00
ainedit: allow adding switches/strings/messages
Allocate space in switch/string/message tables if index is greater than the current size. Its up to the user to allocate their own indices.
This commit is contained in:
@@ -55,6 +55,8 @@ mem_alloc void *_xrealloc(void *ptr, size_t size, const char *func);
|
||||
#define xstrdup(str) _xstrdup(str, __func__)
|
||||
mem_alloc char *_xstrdup(const char *in, const char *func);
|
||||
|
||||
mem_alloc void *xrealloc_array(void *dst, size_t old_nmemb, size_t new_nmemb, size_t size);
|
||||
|
||||
#define max(a, b) \
|
||||
({ \
|
||||
__typeof__ (a) _a = (a); \
|
||||
|
||||
+92
-13
@@ -200,11 +200,44 @@ static int32_t parse_integer_constant(possibly_unused struct asm_state *state, c
|
||||
return i;
|
||||
}
|
||||
|
||||
static uint32_t asm_resolve_arg(struct asm_state *state, enum instruction_argtype type, const char *arg)
|
||||
static void realloc_switch_table(struct ain *ain, int i)
|
||||
{
|
||||
if (i < ain->nr_switches)
|
||||
return;
|
||||
ain->switches = xrealloc_array(ain->switches, ain->nr_switches, i+1, sizeof(struct ain_switch));
|
||||
ain->nr_switches = i+1;
|
||||
}
|
||||
|
||||
static void realloc_switch_cases(struct ain_switch *swi, int i)
|
||||
{
|
||||
if (i < swi->nr_cases)
|
||||
return;
|
||||
swi->cases = xrealloc_array(swi->cases, swi->nr_cases, i+1, sizeof(struct ain_switch_case));
|
||||
swi->nr_cases = i+1;
|
||||
}
|
||||
|
||||
static void realloc_string_table(struct ain *ain, int i)
|
||||
{
|
||||
if (i < ain->nr_strings)
|
||||
return;
|
||||
ain->strings = xrealloc_array(ain->strings, ain->nr_strings, i+1, sizeof(struct string*));
|
||||
ain->nr_strings = i+1;
|
||||
}
|
||||
|
||||
static void realloc_message_table(struct ain *ain, int i)
|
||||
{
|
||||
if (i < ain->nr_messages)
|
||||
return;
|
||||
ain->messages = xrealloc_array(ain->messages, ain->nr_messages, i+1, sizeof(struct string*));
|
||||
ain->nr_messages = i+1;
|
||||
}
|
||||
|
||||
static uint32_t asm_resolve_arg(struct asm_state *state, enum opcode opcode, enum instruction_argtype type, const char *arg)
|
||||
{
|
||||
if (state->flags & ASM_RAW)
|
||||
type = T_INT;
|
||||
|
||||
struct ain *ain = state->ain;
|
||||
switch (type) {
|
||||
case T_INT:
|
||||
return parse_integer_constant(state, arg);
|
||||
@@ -219,8 +252,13 @@ static uint32_t asm_resolve_arg(struct asm_state *state, enum instruction_argtyp
|
||||
}
|
||||
case T_SWITCH: {
|
||||
int i = parse_integer_constant(state, arg);
|
||||
if (i < 0 || i >= state->ain->nr_switches)
|
||||
if (i < 0)
|
||||
ASM_ERROR(state, "Invalid switch number: %d", i);
|
||||
realloc_switch_table(ain, i);
|
||||
if (opcode == SWITCH)
|
||||
ain->switches[i].case_type = AIN_SWITCH_INT;
|
||||
else if (opcode == STRSWITCH)
|
||||
ain->switches[i].case_type = AIN_SWITCH_STRING;
|
||||
return i;
|
||||
}
|
||||
case T_ADDR: {
|
||||
@@ -232,17 +270,18 @@ static uint32_t asm_resolve_arg(struct asm_state *state, enum instruction_argtyp
|
||||
}
|
||||
case T_FUNC: {
|
||||
char *u = utf2sjis(arg, strlen(arg));
|
||||
struct ain_function *f = ain_get_function(state->ain, u);
|
||||
struct ain_function *f = ain_get_function(ain, u);
|
||||
free(u);
|
||||
if (!f)
|
||||
ASM_ERROR(state, "Unable to resolve function: '%s'", arg);
|
||||
return f - state->ain->functions;
|
||||
return f - ain->functions;
|
||||
}
|
||||
case T_STRING: {
|
||||
if (state->flags & ASM_NO_STRINGS) {
|
||||
int32_t i = parse_integer_constant(state, arg);
|
||||
if (i < 0 || i >= state->ain->nr_strings)
|
||||
if (i < 0)
|
||||
ASM_ERROR(state, "String index out of bounds: '%s'", arg);
|
||||
realloc_string_table(ain, i);
|
||||
return i;
|
||||
}
|
||||
return asm_add_string(state, arg);
|
||||
@@ -250,8 +289,9 @@ static uint32_t asm_resolve_arg(struct asm_state *state, enum instruction_argtyp
|
||||
case T_MSG: {
|
||||
if (state->flags & ASM_NO_STRINGS) {
|
||||
int32_t i = parse_integer_constant(state, arg);
|
||||
if (i < 0 || i >= state->ain->nr_messages)
|
||||
if (i < 0)
|
||||
ASM_ERROR(state, "Message index out of bounds: '%s'", arg);
|
||||
realloc_message_table(ain, i);
|
||||
return i;
|
||||
}
|
||||
return asm_add_message(state, arg);
|
||||
@@ -386,6 +426,7 @@ void handle_pseudo_op(struct asm_state *state, struct parse_instruction *instr)
|
||||
} else {
|
||||
c = parse_integer_constant(state, kv_A(*instr->args, 1)->text);
|
||||
}
|
||||
realloc_switch_cases(swi, n_case);
|
||||
swi->cases[n_case].address = state->buf_ptr;
|
||||
swi->cases[n_case].value = c;
|
||||
break;
|
||||
@@ -399,23 +440,61 @@ void handle_pseudo_op(struct asm_state *state, struct parse_instruction *instr)
|
||||
}
|
||||
case PO_STR: {
|
||||
int n_str = parse_integer_constant(state, kv_A(*instr->args, 0)->text);
|
||||
if (n_str < 0 || n_str >= state->ain->nr_strings)
|
||||
if (n_str < 0 || n_str)
|
||||
ASM_ERROR(state, "Invalid string index: %d", n_str);
|
||||
free_string(state->ain->strings[n_str]);
|
||||
realloc_string_table(state->ain, n_str);
|
||||
if (state->ain->strings[n_str])
|
||||
free_string(state->ain->strings[n_str]);
|
||||
state->ain->strings[n_str] = string_dup(kv_A(*instr->args, 1));
|
||||
break;
|
||||
}
|
||||
case PO_MSG: {
|
||||
int n_msg = parse_integer_constant(state, kv_A(*instr->args, 0)->text);
|
||||
if (n_msg < 0 || n_msg >= state->ain->nr_messages)
|
||||
if (n_msg < 0)
|
||||
ASM_ERROR(state, "Invalid message index: %d", n_msg);
|
||||
free_string(state->ain->messages[n_msg]);
|
||||
realloc_message_table(state->ain, n_msg);
|
||||
if (state->ain->messages[n_msg])
|
||||
free_string(state->ain->messages[n_msg]);
|
||||
state->ain->messages[n_msg] = string_dup(kv_A(*instr->args, 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void validate_ain(struct ain *ain)
|
||||
{
|
||||
for (int i = 0; i < ain->nr_strings; i++) {
|
||||
if (ain->strings[i])
|
||||
continue;
|
||||
WARNING("String 0x%x unallocated", i);
|
||||
ain->strings[i] = make_string("", 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ain->nr_messages; i++) {
|
||||
if (ain->messages[i])
|
||||
continue;
|
||||
WARNING("Message 0x%x unallocated", i);
|
||||
ain->messages[i] = make_string("", 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ain->nr_switches; i++) {
|
||||
if (!ain->switches[i].nr_cases)
|
||||
WARNING("Switch 0x%x unallocated", i);
|
||||
}
|
||||
|
||||
if (ain->main < 0 || ain->main >= ain->nr_functions)
|
||||
ERROR("Invalid main function: %d", ain->main);
|
||||
if (strcmp(ain->functions[ain->main].name, "main"))
|
||||
WARNING("Main function is not named 'main': '%s'", ain->functions[ain->main].name);
|
||||
|
||||
if (ain->MSGF.present) {
|
||||
if (ain->msgf < 0 || ain->msgf >= ain->nr_functions)
|
||||
ERROR("Invalid message function: %d", ain->msgf);
|
||||
if (strcmp(ain->functions[ain->msgf].name, "message"))
|
||||
WARNING("Message function is not named 'message': '%s' (%d)", ain->functions[ain->msgf].name, ain->msgf);
|
||||
}
|
||||
}
|
||||
|
||||
void asm_assemble_jam(const char *filename, struct ain *ain, uint32_t flags)
|
||||
{
|
||||
struct asm_state state;
|
||||
@@ -445,7 +524,7 @@ void asm_assemble_jam(const char *filename, struct ain *ain, uint32_t flags)
|
||||
|
||||
// NOTE: special case: we need to record the new function address in the ain structure
|
||||
if (idef->opcode == FUNC) {
|
||||
state.func = asm_resolve_arg(&state, T_INT, kv_A(*instr->args, 0)->text);
|
||||
state.func = asm_resolve_arg(&state, FUNC, T_INT, kv_A(*instr->args, 0)->text);
|
||||
state.ain->functions[state.func].address = state.buf_ptr + 6;
|
||||
asm_write_opcode(&state, FUNC);
|
||||
asm_write_argument(&state, state.func);
|
||||
@@ -454,7 +533,7 @@ void asm_assemble_jam(const char *filename, struct ain *ain, uint32_t flags)
|
||||
|
||||
asm_write_opcode(&state, instr->opcode);
|
||||
for (int a = 0; a < idef->nr_args; a++) {
|
||||
asm_write_argument(&state, asm_resolve_arg(&state, idef->args[a], kv_A(*instr->args, a)->text));
|
||||
asm_write_argument(&state, asm_resolve_arg(&state, idef->opcode, idef->args[a], kv_A(*instr->args, a)->text));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,7 +569,7 @@ void asm_assemble_jam(const char *filename, struct ain *ain, uint32_t flags)
|
||||
ain->nr_messages = state.messages.size;
|
||||
}
|
||||
|
||||
// TODO: verify integrity of ain file (e.g. does MAIN still point to a valid function? etc.)
|
||||
validate_ain(ain);
|
||||
|
||||
fini_asm_state(&state);
|
||||
}
|
||||
|
||||
@@ -58,6 +58,14 @@ mem_alloc char *_xstrdup(const char *in, const char *func)
|
||||
return out;
|
||||
}
|
||||
|
||||
mem_alloc void *xrealloc_array(void *dst, size_t old_nmemb, size_t new_nmemb, size_t size)
|
||||
{
|
||||
dst = xrealloc(dst, new_nmemb * size);
|
||||
if (new_nmemb > old_nmemb)
|
||||
memset((char*)dst + old_nmemb*size, 0, (new_nmemb - old_nmemb) * size);
|
||||
return dst;
|
||||
}
|
||||
|
||||
noreturn void sys_verror(const char *fmt, va_list ap)
|
||||
{
|
||||
vfprintf(stderr, fmt, ap);
|
||||
|
||||
Reference in New Issue
Block a user