strings: store size together with text in memory

This commit is contained in:
Nunuhara Cabbage
2019-10-07 16:54:46 -07:00
parent 626e4f47d7
commit 53dc8a7a44
5 changed files with 64 additions and 48 deletions
+21 -2
View File
@@ -28,6 +28,7 @@
#include "ain.h"
#include "little_endian.h"
#include "instructions.h"
#include "vm_string.h"
static const char *errtab[AIN_MAX_ERROR] = {
[AIN_SUCCESS] = "Success",
@@ -86,6 +87,24 @@ static char **read_strings(struct ain_reader *r, int count)
return strings;
}
static struct string *read_vm_string(struct ain_reader *r)
{
size_t len = strlen((char*)r->buf + r->index);
struct string *s = make_string((char*)r->buf + r->index, len);
s->literal = true;
r->index += len + 1;
return s;
}
static struct string **read_vm_strings(struct ain_reader *r, int count)
{
struct string **strings = calloc(count, sizeof(struct string*));
for (int i = 0; i < count; i++) {
strings[i] = read_vm_string(r);
}
return strings;
}
static struct ain_variable *read_variables(struct ain_reader *r, int count)
{
struct ain_variable *variables = calloc(count, sizeof(struct ain_variable));
@@ -260,7 +279,7 @@ static bool read_tag(struct ain_reader *r, struct ain *ain)
int32_t count = read_int32(r);
ain->structures = read_structures(r, count);
} else if (TAG_EQ("MSG0")) {
ain->messages = read_strings(r, read_int32(r));
ain->messages = read_vm_strings(r, read_int32(r));
} else if (TAG_EQ("MAIN")) {
ain->main = read_int32(r);
} else if (TAG_EQ("MSGF")) {
@@ -274,7 +293,7 @@ static bool read_tag(struct ain_reader *r, struct ain *ain)
} else if (TAG_EQ("GVER")) {
ain->game_version = read_int32(r);
} else if (TAG_EQ("STR0")) {
ain->strings = read_strings(r, read_int32(r));
ain->strings = read_vm_strings(r, read_int32(r));
} else if (TAG_EQ("FNAM")) {
ain->filenames = read_strings(r, read_int32(r));
} else if (TAG_EQ("OJMP")) {
+4 -2
View File
@@ -21,6 +21,8 @@
#include <stdbool.h>
#include <stddef.h>
#include "vm_string.h"
struct ain;
enum ain_error {
@@ -160,13 +162,13 @@ struct ain {
struct ain_global *globals;
struct ain_initval *global_initvals;
struct ain_struct *structures;
char **messages;
struct string **messages;
int32_t main;
int32_t msgf;
struct ain_library *libraries;
struct ain_switch *switches;
int32_t game_version;
char **strings;
struct string **strings;
char **filenames;
int32_t ojmp;
struct ain_function_type *function_types;
+21 -24
View File
@@ -18,45 +18,42 @@
#include <stdio.h>
#include <string.h>
#include "system4.h"
#include "sys4_string.h"
#include "vm_string.h"
struct string make_string(char *str, size_t len)
struct string *make_string(const char *str, unsigned int len)
{
return (struct string) {
.str = str,
.len = len,
.mutable = false
};
struct string *s = xmalloc(sizeof(struct string) + len + 1);
s->size = len;
s->literal = false;
memcpy(s->text, str, len);
s->text[len] = '\0';
return s;
}
void free_string(struct string *str)
{
if (str->mutable)
free(str->str);
if (!str->literal)
free(str);
}
void string_add(struct string *a, struct string *b)
struct string *string_append(struct string *a, struct string *b)
{
if (a->mutable) {
a->str = xrealloc(a->str, a->len + b->len + 1);
if (!a->literal) {
a = xrealloc(a, sizeof(struct string) + a->size + b->size + 1);
} else {
char *literal = a->str;
a->str = xmalloc(a->len + b->len + 1);
memcpy(a->str, literal, a->len + 1);
struct string *tmp = xmalloc(sizeof(struct string) + a->size + b->size + 1);
memcpy(tmp, a, sizeof(struct string) + a->size);
a = tmp;
}
memcpy(a->str + a->len, b->str, b->len + 1);
a->len = a->len + b->len;
memcpy(a->text + a->size, b->text, b->size + 1);
a->size = a->size + b->size;
return a;
}
struct string integer_to_string(int n)
struct string *integer_to_string(int n)
{
char buf[513];
int len = snprintf(buf, 512, "%d" ,n);
buf[512] = '\0';
return (struct string) {
.str = xstrdup(buf),
.len = len,
.mutable = true
};
return make_string(buf, len);
}
+12 -14
View File
@@ -18,7 +18,7 @@
#include <string.h>
#include "system4.h"
#include "sys4_string.h"
#include "vm_string.h"
#include "ain.h"
#include "instructions.h"
#include "little_endian.h"
@@ -35,7 +35,7 @@ static int stack_ptr = 0;
// Separate stack for strings
// Not sure exactly how System40.exe handles strings.
// Further testing required to ensure this approach doesn't break anything.
static struct string string_stack[1024];
static struct string *string_stack[1024];
static int string_stack_ptr = 0;
//static struct frame *frame_stack[1024];
@@ -93,16 +93,15 @@ static int32_t stack_pop_ref(void)
static void stack_push_string_literal(int32_t no)
{
// FIXME: should store string length when reading AIN
string_stack[string_stack_ptr++] = make_string(ain->strings[no], strlen(ain->strings[no]));
string_stack[string_stack_ptr++] = ain->strings[no];
}
static void stack_push_string(struct string *str)
{
string_stack[string_stack_ptr++] = *str;
string_stack[string_stack_ptr++] = str;
}
static struct string stack_pop_string(void)
static struct string *stack_pop_string(void)
{
string_stack_ptr--;
return string_stack[string_stack_ptr];
@@ -111,12 +110,12 @@ static struct string stack_pop_string(void)
static void stack_toss_string(void)
{
string_stack_ptr--;
free_string(&string_stack[string_stack_ptr]);
free_string(string_stack[string_stack_ptr]);
}
static struct string *stack_peek_string(void)
{
return &string_stack[string_stack_ptr-1];
return string_stack[string_stack_ptr-1];
}
/*
@@ -158,7 +157,7 @@ static void system_call(int32_t code)
sys_exit(stack_pop());
break;
case 0x6: // system.Output(string szText)
sys_message("%s", stack_peek_string()->str);
sys_message("%s", stack_peek_string()->text);
// XXX: caller S_POPs
break;
case 0x14: // system.Peek()
@@ -174,7 +173,7 @@ static void system_call(int32_t code)
static void execute_instruction(int16_t opcode)
{
int32_t index, a, b, v;
struct string sa, sb;
struct string *sa, *sb;
const char *opcode_name = "UNKNOWN";
switch (opcode) {
//
@@ -396,12 +395,11 @@ static void execute_instruction(int16_t opcode)
case S_ADD:
sb = stack_pop_string();
sa = stack_pop_string();
string_add(&sa, &sb);
stack_push_string(&sa);
sa = string_append(sa, sb);
stack_push_string(sa);
break;
case I_STRING:
sa = integer_to_string(stack_pop());
stack_push_string(&sa);
stack_push_string(integer_to_string(stack_pop()));
break;
// -- NOOPs ---
case FUNC:
+6 -6
View File
@@ -21,14 +21,14 @@
#include <stddef.h>
struct string {
char *str;
size_t len;
bool mutable;
unsigned int size;
bool literal;
char text[];
};
struct string make_string(char *str, size_t len);
struct string *make_string(const char *str, unsigned int len);
void free_string(struct string *str);
void string_add(struct string *a, struct string *b);
struct string integer_to_string(int n);
struct string *string_append(struct string *a, struct string *b);
struct string *integer_to_string(int n);
#endif