Implement part of connection parsing
authorLukáš Jiřiště <gymnazium.jiriste@gmail.com>
Wed, 17 Sep 2025 13:57:03 +0000 (15:57 +0200)
committerLukáš Jiřiště <gymnazium.jiriste@gmail.com>
Wed, 17 Sep 2025 13:57:03 +0000 (15:57 +0200)
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<t_id> for
pins and buses respectively.

src/c_load.c

index d12096726d8835c75ae67f5ef73dd4293c0d8368..a1488d87336bceb8dec6a322998d1d390d92d68d 100644 (file)
@@ -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);
 }