From e5a85f68ae3e7dbd7c0db52badff7246f4cebfd4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Luk=C3=A1=C5=A1=20Ji=C5=99i=C5=A1t=C4=9B?= Date: Wed, 17 Sep 2025 15:57:03 +0200 Subject: [PATCH] Implement part of connection parsing This is a broken commit. I came this far before I realized it will be better to store buses as vectors of ids in the name_to_id (formerly io_to_id) dictionary. That will make accessing the dictionary and iteration over the pins of buses much easier. name_to_id dict will therefore hold union of t_id and t_vec for pins and buses respectively. --- src/c_load.c | 382 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 368 insertions(+), 14 deletions(-) diff --git a/src/c_load.c b/src/c_load.c index d120967..a1488d8 100644 --- a/src/c_load.c +++ b/src/c_load.c @@ -226,7 +226,7 @@ typedef struct s_part t_vec nodes; t_vec mosfets; t_dict used_parts; - t_dict io_to_node; + t_dict name_to_node; } t_part; int cmp_parts_void(const void *a_v, const void *b_v) @@ -242,7 +242,7 @@ int cmp_parts_void(const void *a_v, const void *b_v) typedef union u_part_spec { char *name; - const t_part *part; + t_part *part; } t_part_spec; int cmp_strings_void(const void *a_v, const void *b_v) @@ -262,7 +262,7 @@ int init_new_part(t_part *part) part->name = NULL; res = ft_vec_init(&part->nodes, sizeof(t_node)); res = res || ft_vec_init(&part->mosfets, sizeof(t_mosfet)); - res = res || ft_dict_init(&part->io_to_node, sizeof(char *), sizeof(t_node *), cmp_strings_void); + res = res || ft_dict_init(&part->name_to_node, sizeof(char *), sizeof(t_node *), cmp_strings_void); res = res || ft_dict_init(&part->used_parts, sizeof(char *), sizeof(t_part_spec), cmp_strings_void); return (res != success); } @@ -284,7 +284,7 @@ void free_part(t_part *part) ft_vec_free(&part->nodes, free_node); ft_vec_free(&part->mosfets, NULL); ft_dict_free(&part->used_parts, free_string_void, NULL); - ft_dict_free(&part->io_to_node, free_string_void, NULL); + ft_dict_free(&part->name_to_node, free_string_void, NULL); return ; } @@ -302,7 +302,7 @@ void free_part_with_used_names(t_part *part) ft_vec_free(&part->nodes, free_node); ft_vec_free(&part->mosfets, NULL); ft_dict_free(&part->used_parts, free_string_void, free_string_void); - ft_dict_free(&part->io_to_node, free_string_void, NULL); + ft_dict_free(&part->name_to_node, free_string_void, NULL); return ; } @@ -457,7 +457,7 @@ void init_fet_single_io(t_part *fet, t_rbtree_node *io_node, t_node *node, t_ter t_mosfet *mosfet; mosfet = node->connected.vec; - io_node->tree = &fet->io_to_node.tree; + io_node->tree = &fet->name_to_node.tree; io_node->parent = NULL; io_node->is_black = 1; io_node->left = NULL; @@ -486,7 +486,7 @@ void build_tree(t_part *fet, t_rbtree_node *left, t_rbtree_node *root, t_rbtree_ root->right = right; right->parent = root; left->parent = root; - fet->io_to_node.tree.root = root; + fet->name_to_node.tree.root = root; return ; } @@ -498,7 +498,7 @@ void init_fet_io(t_part *fet, t_rbtree_node *io_node_source) const int gate_drain_cmp = cmp_strings_void(&g_gate_str, &g_drain_str); const int drain_source_cmp = cmp_strings_void(&g_drain_str, &g_source_str); - ft_dict_init(&fet->io_to_node, sizeof(char *), sizeof(t_id), cmp_strings_void); + ft_dict_init(&fet->name_to_node, sizeof(char *), sizeof(t_id), cmp_strings_void); init_fet_single_io(fet, io_node_source, ft_vec_access(&fet->nodes, 0), source); init_fet_single_io(fet, io_node_gate, ft_vec_access(&fet->nodes, 1), gate); init_fet_single_io(fet, io_node_drain, ft_vec_access(&fet->nodes, 2), drain); @@ -529,7 +529,7 @@ void initialize_fet_part(t_part *fet, t_type type) init_fet_io(fet, io_nodes); } -const t_part *get_part_from_name(t_catalog *parts_catalog, const char *part_name) +t_part *get_part_from_name(t_catalog *parts_catalog, const char *part_name) { static char memory_for_fets[2 * G_COMPLETE_SIZE_OF_FET_PART]; static t_part *nfet_part = NULL; @@ -602,7 +602,7 @@ int add_pin(t_part *part, const char *name) name_copy = ft_strdup(name); if (!name_copy) return (1); - if (ft_dict_insert(&part->io_to_node, &name_copy, &node->id) != success) + if (ft_dict_insert(&part->name_to_node, &name_copy, &node->id) != success) { free(name_copy); return (1); @@ -610,16 +610,27 @@ int add_pin(t_part *part, const char *name) return (0); } -// For simplicity the index is written in reverse order void fill_index(char *buffer, size_t index) { + size_t size; + const size_t index_orig = index; + + size = 0; + while (index > 0) + { + ++size; + index /= 10; + } + buffer[size] = '\0'; + --size; + index = index_orig; while (index > 0) { - *buffer = '0' + index % 10; + buffer[size] = '0' + index % 10; index /= 10; - ++buffer; + --size; } - *buffer = '\0'; + return ; } static const char g_bus_index_separator[] = "-"; @@ -682,10 +693,353 @@ int prepare_io(t_part *part) return (add_io(part, ft_cget_node_child(io_list, 0))); } +int cmp_ids_void(const void *a_v, const void *b_v) +{ + const t_id *a; + const t_id *b; + + a = a_v; + b = b_v; + return ((a > b) - (a < b)); +} + +t_ft_stat copy_id_void(void *dest_v, const void *src_v) +{ + t_id *dest; + const t_id *src; + + dest = dest_v; + src = src_v; + *dest = *src; + return (success); +} + +t_ft_stat copy_segment_void(void *dest_v, const void *src_v) +{ + t_node_segment *dest; + const t_node_segment *src; + + dest = dest_v; + src = src_v; + *dest = *src; + return (success); +} + +int copy_graph(t_part *main_part, t_part *used_part, t_dict *used_to_main_ids) +{ + const size_t original_mosfet_count = main_part->mosfets.size; + size_t i; + size_t j; + t_id *id; + t_mosfet *used_mosfet; + t_mosfet *new_mosfet; + t_node *used_node; + t_node *new_node; + + i = 0; + while (i < used_part->mosfets.size) + { + used_mosfet = ft_vec_access(&used_part->mosfets, i); + new_mosfet = add_mosfet(&main_part->mosfets, used_mosfet->type, + used_mosfet->position, used_mosfet->orientation); + if (!new_mosfet + || ft_dict_insert(used_to_main_ids, &used_mosfet->id, &new_mosfet->id) != success) + return (1); + *new_mosfet = *used_mosfet; + new_mosfet->id = *(t_id *)ft_dict_access(used_to_main_ids, &new_mosfet->id); + ++i; + } + i = 0; + while (i < used_part->nodes.size) + { + used_node = ft_vec_access(&used_part->nodes, i); + new_node = add_node(&main_part->nodes, used_node->set_state); + if (!new_node + || ft_dict_insert(used_to_main_ids, &used_node->id, &new_node->id)) + return (1); + *new_node = *used_node; + new_node->id = *(t_id *)ft_dict_access(used_to_main_ids, &new_node->id); + if (ft_vec_copy(&new_node->connected, &used_node->connected, copy_id_void, NULL) + || ft_vec_copy(&new_node->connected, &used_node->connected, copy_id_void, NULL) + || ft_vec_copy(&new_node->segments, &used_node->segments, copy_segment_void, NULL)) + return (1); + j = 0; + while (j < new_node->connected.size) + { + id = ft_vec_access(&new_node->connected, j); + *id = *(t_id *)ft_dict_access(used_to_main_ids, &id); + ++j; + } + j = 0; + while (j < new_node->connected_gates.size) + { + id = ft_vec_access(&new_node->connected_gates, j); + *id = *(t_id *)ft_dict_access(used_to_main_ids, &id); + ++j; + } + ++i; + } + i = original_mosfet_count; + while (i < main_part->mosfets.size) + { + new_mosfet = ft_vec_access(&main_part->mosfets, i); + new_mosfet->gate = *(t_id *)ft_dict_access(used_to_main_ids, &new_mosfet->gate); + new_mosfet->drain = *(t_id *)ft_dict_access(used_to_main_ids, &new_mosfet->drain); + new_mosfet->source = *(t_id *)ft_dict_access(used_to_main_ids, &new_mosfet->source); + ++i; + } + return (0); +} + +const char g_part_name_separator[] = "."; + +int record_used_io(t_part *main_part, t_part *used_part, const char *used_part_name, t_dict *used_to_main_ids) +{ + t_dict_traversal named_nodes; + t_dict_entry dict_entry; + size_t name_size; + char *name; + char *pin_name; + t_id id; + + if (ft_dict_traversal_init(&named_nodes, &used_part->name_to_node) != success) + return (1); + dict_entry = ft_dict_traverse_full(&named_nodes); + while (dict_entry.key) + { + name = *(char **)dict_entry.key; + id = *(t_id *)dict_entry.el; + if (ft_strchr(name, *g_part_name_separator)) + continue ; + name_size = ft_strlen(used_part_name) + 1 + ft_strlen(name) + 1; + pin_name = malloc(name_size); + ft_strlcpy(pin_name, used_part_name, name_size); + ft_strlcat(pin_name, g_part_name_separator, name_size); + ft_strlcat(pin_name, name, name_size); + id = *(t_id *)ft_dict_access(used_to_main_ids, &id); + if (ft_dict_insert(&main_part->name_to_node, &pin_name, &id)) + { + ft_dict_traversal_free(&named_nodes); + return (1); + } + dict_entry = ft_dict_traverse_full(&named_nodes); + } + ft_dict_traversal_free(&named_nodes); + return (0); +} + +int embed_part(t_part *main_part, t_part *used_part, const char *used_part_name) +{ + t_dict used_to_main_ids; + + ft_dict_init(&used_to_main_ids, sizeof(t_id), sizeof(t_id), cmp_ids_void); + if (copy_graph(main_part, used_part, &used_to_main_ids)) + { + ft_dict_free(&used_to_main_ids, NULL, NULL); + return (1); + } + if (record_used_io(main_part, used_part, used_part_name, &used_to_main_ids)) + { + ft_dict_free(&used_to_main_ids, NULL, NULL); + return (1); + } + ft_dict_free(&used_to_main_ids, NULL, NULL); + return (0); +} + +int build_part_graph(t_part *part); + +int import_subparts(t_part *part) +{ + t_dict_traversal used_parts_traversal; + t_dict_entry dict_entry; + char *used_part_name; + t_part *used_part; + + if (ft_dict_traversal_init(&used_parts_traversal, &part->used_parts) != success) + return (1); + dict_entry = ft_dict_traverse_full(&used_parts_traversal); + while (dict_entry.key) + { + used_part_name = *(char **)dict_entry.key; + used_part = ((t_part_spec *)dict_entry.el)->part; + if (build_part_graph(used_part) || embed_part(part, used_part, used_part_name)) + { + ft_dict_traversal_free(&used_parts_traversal); + return (1); + } + dict_entry = ft_dict_traverse_full(&used_parts_traversal); + } + return (0); +} + +int is_state_setting_connection(const t_parse_tree_node *connection) +{ + return (!ft_strcmp(ft_cget_node_child(connection, 0)->token.type, g_defined_tokens[node_state].type) + || !ft_strcmp(ft_cget_node_child(connection, 2)->token.type, g_defined_tokens[node_state].type)); +} + +int is_pin_pin_connection(const t_parse_tree_node *connection) +{ + return (!is_state_setting_connection(connection) + && !ft_strcmp(ft_cget_node_child(connection, 1)->token.type, g_defined_tokens[hyphen].type)); +} + +int is_bus_bus_connection(const t_parse_tree_node *connection) +{ + return (!is_state_setting_connection(connection) + && !ft_strcmp(ft_cget_node_child(connection, 1)->token.type, g_defined_tokens[equal_sign].type)); +} + +t_state parsed_node_to_state(const t_parse_tree_node *state_node) +{ + t_state state; + + state = 0; + while (state < state_count) + { + if (!ft_strcmp(state_node->token.str, g_node_state_strings[state])) + return (state); + ++state; + } + return (unknown); +} + +char *get_pin_name(const t_parse_tree_node *pin_spec) +{ + const char *part_name; + const char *pin_name; + const char *index; + char *whole_name; + const t_parse_tree_node *helper_node; + + if (pin_spec->children.size == 1) + { + part_name = NULL; + helper_node = ft_cget_node_child(pin_spec, 0); + } + else + { + part_name = ft_cget_child_deep(pin_spec, 0, 0, 0)->token.str; + helper_node = ft_cget_node_child(pin_spec, 2); + } + pin_name = ft_cget_child_deep(helper_node, 0, 0, 0)->token.str; + if (helper_node->children.size == 1) + index = NULL; + else + index = ft_cget_child_deep(helper_node, 1, 1, 0)->token.str; + size = ft_strlen(part_name) + (part_name != NULL) * g_part_name_separator + + ft_strlen(pin_name) + (index != NULL) * g_bus_index_separator + ft_strlen(index) + 1; + whole_name = malloc(size); + whole_name[0] = '\0'; + if (part_name) + { + ft_strlcat(whole_name, part_name, size); + ft_strlcat(whole_name, g_part_name_separator, size); + } + ft_strlcat(whole_name, pin_name, size); + if (index) + { + ft_strlcat(whole_name, g_bus_index_separator, size); + ft_strlcat(whole_name, index, size); + } + return (whole_name); +} + +int set_pin_state(t_part *part, const t_parse_tree_node *pin_spec, t_state state) +{ + char *name; + t_id id; + + name = get_pin_name(pin_spec); + if (!name) + return (1); + id = *(t_id *)ft_dict_access(&part->name_to_node, name); + free(name); + get_node_by_id(&part->nodes, id)->set_state = state; + return (0); +} + +int set_bus_state(t_part *part, const t_parse_tree_node *bus_spec, t_state state) +{ + char *name; + t_id id; + size_t i; + size_t last_index; + size_t index_offset; + const t_parse_tree_node *helper; + + index_offset = get_and_prefill_buffer(&name, part, bus_spec); + helper = ft_cget_node_child(bus_spec, bus_spec->children.size - 1); + if (helper->children.size == 1) + { + i = 1; + last_index = +} + +int set_state_from_connection(t_part *part, const t_parse_tree_node *connection) +{ + t_state state; + const t_parse_tree_node *state_node; + const t_parse_tree_node *helper_node; + t_id id; + + helper_node = ft_cget_node_child(connection, 0); + if (!ft_strcmp(helper_node->token.type, g_defined_tokens[node_state].type)) + { + state_node = helper_node; + helper_node = ft_cget_node_child(connection, 2); + } + else + state_node = ft_cget_node_child(connection, 2); + state = parsed_node_to_state(state_node); + if (!ft_strcmp(helper_node->token.type, "PinSpec")) + return (set_pin_state(part, helper_node, state)); + if (!ft_strcmp(ft_cget_node_child(connection, 1)->token.type, g_defined_tokens[equal_sign].type)) + return (set_bus_state(part, helper_node, state)); + id = tie_bus(part, helper_node); + if (id == INVALID_ID) + return (1); + get_node_by_id(&part->nodes, id)->set_state = state; + return (0); +} + +int add_connection(t_part *part, const t_parse_tree_node *connection) +{ + if (is_state_setting_connection(connection)) + return (set_state_from_connection(part, connection)); + if (is_pin_pin_connection(connection)) + return (add_pin_pin_connection(part, connection)); + if (is_bus_bus_connection(connection)) + return (add_bus_bus_connection(part, connection)); + return (add_pin_bus_connection(part, connection)); +} + +int realise_connections(t_part *part) +{ + const t_parse_tree_node *connection_list; + + connection_list = ft_cget_child_deep(part->parsed_node, 2, 3, 1); + while (connection_list->children.size == 3) + { + if (add_connection(part, ft_cget_node_child(connection_list, 2))) + return (1); + connection_list = ft_cget_node_child(connection_list, 0); + } + return (add_connection(part, ft_cget_node_child(connection_list, 0))); +} + int build_part_graph(t_part *part) { + if (part->is_graph_built == 1) + return (0); if (prepare_io(part)) return (1); + if (import_subparts(part)) + return (1); + if (realise_connections(part)) + return (1); + part->is_graph_built = 1; return (0); } -- 2.30.2