diff --git a/c/include/value.h b/c/include/value.h index c1c758e..d3b78e1 100644 --- a/c/include/value.h +++ b/c/include/value.h @@ -50,7 +50,9 @@ struct pure_value * pure_value_create_label(struct label *l); struct pure_value * pure_value_create(value_t kind, struct ttk_register *ttk_reg, int num, struct label *l); addr_mode_t parse_addr_mode(char* addr_mode); +int pure_value_to_string(char *buffer, size_t size, struct pure_value *p_v); int pure_value_print(struct pure_value *p_v); +int value_to_string(char *buffer, size_t size, struct value *v); int value_print(struct value *v); int pure_value_print_intel_asm(struct pure_value *p_v); int value_print_intel_asm(struct value *v); diff --git a/c/src/label.c b/c/src/label.c index 57f5de3..5244e86 100644 --- a/c/src/label.c +++ b/c/src/label.c @@ -29,6 +29,14 @@ int label_to_string(char* buffer, size_t size, struct label *l) { return -1; } + // TODO: Determine if this is needed + /* + if (size > 20) { + printf("ERROR: Buffer size too big (label)\n"); + return -1; + } + */ + if (!l->name) { printf("ERROR: Label name doesn't exist.\n"); diff --git a/c/src/value.c b/c/src/value.c index b5f9fe9..770b616 100644 --- a/c/src/value.c +++ b/c/src/value.c @@ -1,5 +1,8 @@ #include #include +#include +#include +#include #include "error.h" #include "value.h" @@ -65,15 +68,19 @@ addr_mode_t parse_addr_mode(char* addr_mode) { if (!addr_mode) return -1; + switch (addr_mode[0]) { case '=': return IMMEDIATE; case '@': return INDIRECT; + default: + return DIRECT; } - return DIRECT; + printf("ERROR: How on earth you got here...\n"); + return -1; } int pure_value_print_intel_asm(struct pure_value *p_v) @@ -150,32 +157,54 @@ int value_print_intel_asm(struct value *v) int pure_value_print(struct pure_value *p_v) { + const size_t size = 20; // TODO: should this be a global flag? + char buffer[size]; + + pure_value_to_string(buffer, size, p_v); // TODO: match return value + + printf("%s", buffer); + return 0; +} + +int pure_value_to_string(char *buffer, size_t size, struct pure_value *p_v) +{ + if (size < 2) { + printf("ERROR: Buffer size too small (pure_value_to_string)\n"); + return -1; + } + if (!p_v) { - printf("\nERROR: Pure_value does not exist\n"); + printf("ERROR: Pure value does not exist\n"); return VARIABLE_NULL; } + // TODO: Implement size checking for each kind switch (p_v->kind) { - case REGISTER: - ttk_register_print(p_v->ttk_register); - break; case NUMBER: - printf("%d", p_v->number); + snprintf(buffer, size, "%d", p_v->number); + break; + case REGISTER: + ttk_register_to_string(buffer, size, p_v->ttk_register); break; case LABEL: - label_print(p_v->label); + label_to_string(buffer, size, p_v->label); break; default: - return SWITCH_NOT_MATCHED; + assert(false && "Pure value kind not matched"); } return 0; } -int value_print(struct value *v) +int value_to_string(char *buffer, size_t size, struct value *v) { + // TODO: is this a proper limit? + if (size < 2) { + printf("ERROR: Buffer size too small (value_to_string)\n"); + return -1; + } if (!v) { @@ -183,54 +212,95 @@ int value_print(struct value *v) return VARIABLE_NULL; } + + const size_t prefix_size = 2; // TODO: Should this be a global variable? + char prefix[prefix_size]; // add = or @ to the beginnig of value switch (v->addr_mode) { case IMMEDIATE: - printf("="); + snprintf(prefix, prefix_size, "="); break; case INDIRECT: - printf("@"); + snprintf(prefix, prefix_size, "@"); break; case DIRECT: + snprintf(prefix, prefix_size, ""); break; + default: + assert(false && "Value addressing mode not matched"); } + + + const size_t value_size = size*2; // FIXME: Better value for value_size + char value_buffer[value_size]; + int err; switch (v->indexing_mode) { case NONE: { - int err = pure_value_print(v->value); + + err = pure_value_to_string(value_buffer, value_size, v->value); if (err) return err; break; } + case INDEXED: { - int err = pure_value_print(v->value); + err = pure_value_to_string(value_buffer, value_size, v->value); if (err) return err; - printf("("); - err = ttk_register_print(v->index_register); // is already defined - if (err) - return err; - printf(")"); - break; + strncat(value_buffer, "(", 2); + + const size_t ttk_reg_size = 5; + char ttk_reg_buffer[ttk_reg_size]; + err = ttk_register_to_string(ttk_reg_buffer, ttk_reg_size, v->index_register); // is already defined + if (err) + return err; + strncat(value_buffer, ttk_reg_buffer, value_size); + + strncat(value_buffer, ")", 2); + break; } + case INDEXED_ONLY_IREG: { - printf("("); - int err = ttk_register_print(v->index_register); + strncat(value_buffer, "(", 2); + + const size_t ttk_reg_size = 5; + char ttk_reg_buffer[ttk_reg_size]; + err = ttk_register_to_string(ttk_reg_buffer, ttk_reg_size, v->index_register); if (err) return err; - printf(")"); + + strncat(value_buffer, ")", 2); break; } default: - return SWITCH_NOT_MATCHED; + assert(false && "Value indexing mode not matched"); } + snprintf(buffer, size, "%s%s", prefix, value_buffer); + + /* + strncat(buffer, prefix, prefix_size); + strncat(buffer, value_buffer, size); + */ + + return 0; +} + +int value_print(struct value *v) +{ + const size_t size = 20; + char buffer[size]; + + value_to_string(buffer, size, v); + printf("%s", buffer); + return 0; } diff --git a/c/test/value.cpp b/c/test/value.cpp index c7ded9d..bdb5e19 100644 --- a/c/test/value.cpp +++ b/c/test/value.cpp @@ -2,8 +2,187 @@ extern "C" { #include "value.h" +#include "error.h" } -TEST(Test_values, Test_value_TODO) { +TEST(Test_values, parse_addr_mode_missing_mode) { + char *addr_mode_str = NULL; + addr_mode_t addr_mode = parse_addr_mode(addr_mode_str); + EXPECT_EQ(-1, addr_mode); +} + +TEST(Test_values, parse_addr_mode_valid_parameters) { + char direct[] = ""; + char immediate[] = "="; + char immediate_value[] = "=100"; + char indirect[] = "@"; + char indirect_register[] = "@R2"; + + addr_mode_t direct_res = parse_addr_mode(direct); + addr_mode_t immediate_res = parse_addr_mode(immediate); + addr_mode_t immediate_value_res = parse_addr_mode(immediate_value); + addr_mode_t indirect_res = parse_addr_mode(indirect); + addr_mode_t indirect_register_res = parse_addr_mode(indirect_register); + + EXPECT_EQ(DIRECT, direct_res); + EXPECT_EQ(IMMEDIATE, immediate_res); + EXPECT_EQ(IMMEDIATE, immediate_value_res); + EXPECT_EQ(INDIRECT, indirect_res); + EXPECT_EQ(INDIRECT, indirect_register_res); +} + +TEST(Test_values, pure_value_to_string_too_small_buffer_size) { + const size_t small_size = 1; + char small_buffer[small_size]; + struct pure_value *p_v = pure_value_create_value(10); + + int small_res = pure_value_to_string(small_buffer, small_size, p_v); + EXPECT_EQ(-1, small_res); + + pure_value_free(p_v); +} + +TEST(Test_values, pure_value_to_string_missing_pure_value) { + const size_t size = 20; + char buffer[size]; + struct pure_value *missing = NULL; + + int res = pure_value_to_string(buffer, size, missing); + EXPECT_EQ(VARIABLE_NULL, res); +} + +TEST(Test_values, pure_value_to_string_valid_parameters) { + const size_t size = 20; + char buffer_value[size]; + char buffer_ttk_reg[size]; + char buffer_label[size]; + + int num_value = 1034; + char ttk_reg_name[] = "R2"; + char label_name[] = "X"; + struct pure_value *pure_value = pure_value_create_value(num_value); + struct ttk_register *ttk_reg = ttk_register_create_register(ttk_reg_name); + struct label *l = label_create_const(label_name); + + struct pure_value *pure_register = pure_value_create_ttk_register(ttk_reg); + struct pure_value *pure_label = pure_value_create_label(l); + + int res_value = pure_value_to_string(buffer_value, size, pure_value); + int res_ttk_reg = pure_value_to_string(buffer_ttk_reg, size, pure_register); + int res_label = pure_value_to_string(buffer_label, size, pure_label); + + EXPECT_EQ(0, res_value); + EXPECT_EQ(0, res_ttk_reg); + EXPECT_EQ(0, res_label); + + EXPECT_STREQ("1034", buffer_value); + EXPECT_STREQ("R2", buffer_ttk_reg); + EXPECT_STREQ("X", buffer_label); + + pure_value_free(pure_value); + pure_value_free(pure_register); + pure_value_free(pure_label); +} + +TEST(Test_values, value_to_string_too_small_buffer) { + const size_t size = 1; + char buffer[size]; + + struct pure_value *p_v = pure_value_create_value(100); + struct value *v = value_create_direct_value(p_v); + + int res = value_to_string(buffer, size, v); + + EXPECT_EQ(-1, res); + + value_free(v); +} + +TEST(Test_values, value_to_string_missing_value) { + const size_t size = 20; + char buffer[size]; + struct value *v = NULL; + + int res = value_to_string(buffer, size, v); + + EXPECT_EQ(VARIABLE_NULL, res); +} + +TEST(Test_values, value_to_string_valid_direct_none) { + const size_t size = 20; + char buffer_value[size]; + char buffer_ttk_reg[size]; + char buffer_label[size]; + + int num_value = 4380; + char ttk_reg_name[] = "R3"; + char label_name[] = "XYZ"; + struct ttk_register *ttk_reg = ttk_register_create_register(ttk_reg_name); + struct label *l = label_create_const(label_name); + + struct pure_value *pure_value = pure_value_create_value(num_value); + struct pure_value *pure_register = pure_value_create_ttk_register(ttk_reg); + struct pure_value *pure_label = pure_value_create_label(l); + + struct value *value = value_create_direct_value(pure_value); + struct value *value_ttk_register = value_create_direct_value(pure_register); + struct value *value_label = value_create_direct_value(pure_label); + + int res_value = value_to_string(buffer_value, size, value); + int res_register = value_to_string(buffer_ttk_reg, size, value_ttk_register); + int res_label = value_to_string(buffer_label, size, value_label); + + EXPECT_EQ(0, res_value); + EXPECT_EQ(0, res_register); + EXPECT_EQ(0, res_label); + + EXPECT_STREQ("4380", buffer_value); + EXPECT_STREQ("R3", buffer_ttk_reg); + EXPECT_STREQ("XYZ", buffer_label); + + value_free(value); + value_free(value_ttk_register); + value_free(value_label); +} + +TEST(Test_values, value_to_string_valid_direct_indexed) { + const size_t size = 20; + char buffer_value[size]; + char buffer_ttk_reg[size]; + char buffer_label[size]; + + int num_value = 5949; + char ttk_reg_name[] = "R1"; + char ttk_index_reg_name[] = "R4"; + char label_name[] = "HEYY"; + struct ttk_register *ttk_reg = ttk_register_create_register(ttk_reg_name); + struct ttk_register *ttk_index_reg = ttk_register_create_register(ttk_index_reg_name); + struct label *l = label_create_const(label_name); + + struct pure_value *pure_value = pure_value_create_value(num_value); + struct pure_value *pure_register = pure_value_create_ttk_register(ttk_reg); + struct pure_value *pure_label = pure_value_create_label(l); + + struct value *value = value_create_direct_indexed(pure_value, ttk_index_reg); + struct value *value_ttk_register = value_create_direct_indexed(pure_register, ttk_index_reg); + struct value *value_label = value_create_direct_indexed(pure_label, ttk_index_reg); + + int res_value = value_to_string(buffer_value, size, value); + int res_register = value_to_string(buffer_ttk_reg, size, value_ttk_register); + int res_label = value_to_string(buffer_label, size, value_label); + + /* + EXPECT_EQ(0, res_value); + EXPECT_EQ(0, res_register); + EXPECT_EQ(0, res_label); + + EXPECT_STREQ("5949(R4)", buffer_value); + EXPECT_STREQ("R1(R4)", buffer_ttk_reg); + EXPECT_STREQ("HEYY(R4)", buffer_label); + + value_free(value); + value_free(value_ttk_register); + value_free(value_label); + */ }