Finish parsing of files
authorLukáš Jiřiště <gymnazium.jiriste@gmail.com>
Sat, 20 Sep 2025 20:04:38 +0000 (22:04 +0200)
committerLukáš Jiřiště <gymnazium.jiriste@gmail.com>
Sat, 20 Sep 2025 20:10:56 +0000 (22:10 +0200)
The load instruction now is able to go through the file and properly
parse it into a graph.
It mostly fails silently for now.
It also just deletes the graph as soon as it is constructed, because the
transfer is not yet implemented (but should be easy).
Some additional fixes were done, now valgrind does not report any leak
(except for ncurses).
A sample test was also added which should feature most of the current
capabilities. It does not test subbus access so far.

Libft
TODO
samples/test [new file with mode: 0644]
src/c_load.c
src/main.c

diff --git a/Libft b/Libft
index 7ea0e5eab36b56b286a76770d618ff5ea5fc3be7..30f8df1bfda39333988817e9f5312e71905dbc34 160000 (submodule)
--- a/Libft
+++ b/Libft
@@ -1 +1 @@
-Subproject commit 7ea0e5eab36b56b286a76770d618ff5ea5fc3be7
+Subproject commit 30f8df1bfda39333988817e9f5312e71905dbc34
diff --git a/TODO b/TODO
index 67bf114db8b51aed6b758d6f54ea88c20a72e1d9..f6f59979d5b6478e8ec942d1a675f9b658becd77 100644 (file)
--- a/TODO
+++ b/TODO
@@ -4,8 +4,8 @@ fix file not loading when load command repeated with empty command
 make build_graph not output
 rewrite command parsing (what I've created is just ugly)
 come up with better file structure
-create language to write circuits in (circuit language?) (something like MHRD language?)
 implement circuit builder that converts circuit language to FET_sim representation in order to simulate
+       - mostly done
 Group nodes and mosfets in a "graph" structure
 add even more simulation commands(eg. delete node/fet)
 test the project
diff --git a/samples/test b/samples/test
new file mode 100644 (file)
index 0000000..36ed76a
--- /dev/null
@@ -0,0 +1,509 @@
+not;
+       connectors:
+               in,
+               out;
+       parts:
+               n - n,
+               p - p;
+       connections:
+               n.source - p.drain,
+               n.gate - p.gate,
+               p.source - on,
+               n.drain - off,
+               in - n.gate,
+               out - n.source;
+
+nmos_nand;
+       connectors:
+               a,
+               b,
+               out,
+               source;
+       parts:
+               na - n,
+               nb - n;
+       connections:
+               a - na.gate,
+               b - nb.gate,
+               na.source - out,
+               na.drain - nb.source,
+               nb.drain - source,
+               source - off,
+               out - pull_up;
+
+pmos_nor;
+       connectors:
+               a,
+               b,
+               out,
+               source;
+       parts:
+               pa - p,
+               pb - p;
+       connections:
+               a - pa.gate,
+               b - pb.gate,
+               pa.source - source,
+               pa.drain - pb.source,
+               pb.drain - out,
+               source - on,
+               out - pull_down;
+
+nmos_nor;
+       connectors:
+               a,
+               b,
+               out,
+               source;
+       parts:
+               na - n,
+               nb - n;
+       connections:
+               a - na.gate,
+               b - nb.gate,
+               na.source - nb.source,
+               na.source - out,
+               na.drain - nb.drain,
+               na.drain - source,
+               source - off,
+               out - pull_up;
+
+pmos_nand;
+       connectors:
+               a,
+               b,
+               out,
+               source;
+       parts:
+               pa - p,
+               pb - p;
+       connections:
+               a - pa.gate,
+               b - pb.gate,
+               pa.source - pb.source,
+               pa.source - source,
+               pa.drain - pb.drain,
+               pa.drain - out,
+               source - on,
+               out - pull_down;
+
+nand;
+       connectors:
+               a,
+               b,
+               out;
+       parts:
+               p_nand - pmos_nand,
+               n_nand - nmos_nand;
+       connections:
+               a - p_nand.a,
+               a - n_nand.a,
+               b - p_nand.b,
+               b - n_nand.b,
+               out - p_nand.out,
+               out - n_nand.out,
+               out - floating;
+
+nor;
+       connectors:
+               a,
+               b,
+               out;
+       parts:
+               p_nor - pmos_nor,
+               n_nor - nmos_nor;
+       connections:
+               a - p_nor.a,
+               a - n_nor.a,
+               b - p_nor.b,
+               b - n_nor.b,
+               out - p_nor.out,
+               out - n_nor.out,
+               out - floating;
+
+and;
+       connectors:
+               a,
+               b,
+               out;
+       parts:
+               not - not,
+               nand - nand;
+       connections:
+               a - nand.a,
+               b - nand.b,
+               nand.out - not.in,
+               not.out - out;
+
+or;
+       connectors:
+               a,
+               b,
+               out;
+       parts:
+               not - not,
+               nor - nor;
+       connections:
+               a - nor.a,
+               b - nor.b,
+               nor.out - not.in,
+               not.out - out;
+
+xor;
+       connectors:
+               a,
+               b,
+               out;
+       parts:
+               nota - not,
+               notb - not,
+               nand1 - pmos_nand,
+               nand2 - pmos_nand,
+               nor1 - nmos_nor,
+               nor2 - nmos_nor;
+       connections:
+               a - nota.in,
+               b - notb.in,
+               a - nand1.a,
+               b - nand1.b,
+               nota.out - nand2.a,
+               notb.out - nand2.b,
+               nand1.out - nand2.source,
+               nand2.source - floating,
+               a - nor1.a,
+               notb.out - nor1.b,
+               nota.out - nor2.a,
+               b - nor2.b,
+               nor1.out - nor2.source,
+               nor2.source - floating,
+               nor2.out - out,
+               nand2.out - out,
+               out - floating;
+
+not4;
+       connectors:
+               in[4],
+               out[4];
+       parts:
+               n0 - not,
+               n1 - not,
+               n2 - not,
+               n3 - not;
+       connections:
+               in[0] - n0.in,
+               in[1] - n1.in,
+               in[2] - n2.in,
+               in[3] - n3.in,
+               n0.out - out[0],
+               n1.out - out[1],
+               n2.out - out[2],
+               n3.out - out[3];
+
+nand4;
+       connectors:
+               a[4],
+               b[4],
+               out[4];
+       parts:
+               nand0 - nand,
+               nand1 - nand,
+               nand2 - nand,
+               nand3 - nand;
+       connections:
+               a[0] - nand0.a,
+               b[0] - nand0.b,
+               a[1] - nand1.a,
+               b[1] - nand1.b,
+               a[2] - nand2.a,
+               b[2] - nand2.b,
+               a[3] - nand3.a,
+               b[3] - nand3.b,
+               nand0.out - out[0],
+               nand1.out - out[1],
+               nand2.out - out[2],
+               nand3.out - out[3];
+
+nor4;
+       connectors:
+               a[4],
+               b[4],
+               out[4];
+       parts:
+               nor0 - nor,
+               nor1 - nor,
+               nor2 - nor,
+               nor3 - nor;
+       connections:
+               a[0] - nor0.a,
+               b[0] - nor0.b,
+               a[1] - nor1.a,
+               b[1] - nor1.b,
+               a[2] - nor2.a,
+               b[2] - nor2.b,
+               a[3] - nor3.a,
+               b[3] - nor3.b,
+               nor0.out - out[0],
+               nor1.out - out[1],
+               nor2.out - out[2],
+               nor3.out - out[3];
+
+and4;
+       connectors:
+               a[4],
+               b[4],
+               out[4];
+       parts:
+               not - not4,
+               nand - nand4;
+       connections:
+               a = nand.a,
+               b = nand.b,
+               nand.out = not.out,
+               not.out = out;
+
+or4;
+       connectors:
+               a[4],
+               b[4],
+               out[4];
+       parts:
+               not - not4,
+               nor - nor4;
+       connections:
+               a = nor.a,
+               b = nor.b,
+               nor.out = not.out,
+               not.out = out;
+
+xor4;
+       connectors:
+               a[4],
+               b[4],
+               out[4];
+       parts:
+               xor0 - xor,
+               xor1 - xor,
+               xor2 - xor,
+               xor3 - xor;
+       connections:
+               a[0] - xor0.a,
+               b[0] - xor0.b,
+               a[1] - xor1.a,
+               b[1] - xor1.b,
+               a[2] - xor2.a,
+               b[2] - xor2.b,
+               a[3] - xor3.a,
+               b[3] - xor3.b,
+               xor0.out - out[0],
+               xor1.out - out[1],
+               xor2.out - out[2],
+               xor3.out - out[3];
+
+adder;
+       connectors:
+               carry_in,
+               a,
+               b,
+               out,
+               carry_out;
+       parts:
+               xor_main - xor,
+               xor_carry - xor,
+               and_main - and,
+               and_carry - and,
+               or_carry - or;
+       connections:
+               a - xor_main.a,
+               b - xor_main.b,
+               a - and_main.a,
+               b - and_main.b,
+               xor_main.out - xor_carry.a,
+               carry_in - xor_carry.b,
+               xor_main.out - and_carry.a,
+               carry_in - and_carry.b,
+               xor_carry.out - out,
+               and_main.out - or_carry.a,
+               and_carry.out - or_carry.b,
+               or_carry.out - carry_out;
+
+adder4;
+       connectors:
+               carry_in,
+               a[4],
+               b[4],
+               out[4],
+               carry_out;
+       parts:
+               add0 - adder,
+               add1 - adder,
+               add2 - adder,
+               add3 - adder;
+       connections:
+               carry_in - add0.carry_in,
+               add0.carry_out - add1.carry_in,
+               add1.carry_out - add2.carry_in,
+               add2.carry_out - add3.carry_in,
+               add3.carry_out - carry_out,
+               a[0] - add0.a,
+               b[0] - add0.b,
+               out[0] - add0.out,
+               a[1] - add1.a,
+               b[1] - add1.b,
+               out[1] - add1.out,
+               a[2] - add2.a,
+               b[2] - add2.b,
+               out[2] - add2.out,
+               a[3] - add3.a,
+               b[3] - add3.b,
+               out[3] - add3.out;
+
+
+mux;
+       connectors:
+               a,
+               b,
+               sel,
+               out;
+       parts:
+               p_nand_a - pmos_nand,
+               p_nand_b - pmos_nand,
+               n_nand_a - nmos_nand,
+               n_nand_b - nmos_nand,
+               not_sel - not,
+               not_not_out - not;
+       connections:
+               sel - p_nand_a.a,
+               a - p_nand_a.b,
+               sel - not_sel.in,
+               not_sel.out - p_nand_b.a,
+               b - p_nand_b.b,
+               not_not_out.out - out,
+               p_nand_a.out - not_not_out.in,
+               p_nand_b.out - not_not_out.in,
+               n_nand_a.out - not_not_out.in,
+               not_not_out.in - floating,
+               n_nand_a.a - a,
+               n_nand_a.b - not_sel.out,
+               n_nand_a.source - n_nand_b.out,
+               n_nand_b.out - floating,
+               n_nand_b.a - sel,
+               n_nand_b.b - b;
+
+mux1x2;
+       connectors:
+               a,
+               b,
+               sel,
+               out;
+       parts:
+               mux - mux;
+       connections:
+               a - mux.a,
+               b - mux.b,
+               sel - mux.sel,
+               out - mux.out;
+
+mux1x4;
+       connectors:
+               a,
+               b,
+               c,
+               d,
+               sel[2],
+               out;
+       parts:
+               mux_ab - mux1x2,
+               mux_cd - mux1x2,
+               mux_out - mux1x2;
+       connections:
+               a - mux_ab.a,
+               b - mux_ab.b,
+               c - mux_cd.a,
+               d - mux_cd.b,
+               sel[0] - mux_ab.sel,
+               sel[0] - mux_cd.sel,
+               mux_ab.out - mux_out.a,
+               mux_cd.out - mux_out.b,
+               sel[1] - mux_out.sel,
+               mux_out.out - out;
+
+mux4x2;
+       connectors:
+               a[4],
+               b[4],
+               sel,
+               out[4];
+       parts:
+               mux0 - mux,
+               mux1 - mux,
+               mux2 - mux,
+               mux3 - mux;
+       connections:
+               a[0] - mux0.a,
+               b[0] - mux0.b,
+               sel - mux0.sel,
+               mux0.out - out[0],
+               a[1] - mux1.a,
+               b[1] - mux1.b,
+               sel - mux1.sel,
+               mux1.out - out[1],
+               a[2] - mux2.a,
+               b[2] - mux2.b,
+               sel - mux2.sel,
+               mux2.out - out[2],
+               a[3] - mux3.a,
+               b[3] - mux3.b,
+               sel - mux3.sel,
+               mux3.out - out[3];
+
+mux4x4;
+       connectors:
+               a[4],
+               b[4],
+               c[4],
+               d[4],
+               sel[2],
+               out[4];
+       parts:
+               mux_ab - mux4x2,
+               mux_cd - mux4x2,
+               mux_out - mux4x2;
+       connections:
+               a = mux_ab.a,
+               b = mux_ab.b,
+               c = mux_cd.a,
+               d = mux_cd.b,
+               sel[0] - mux_ab.sel,
+               sel[0] - mux_cd.sel,
+               mux_ab.out = mux_out.a,
+               mux_cd.out = mux_out.b,
+               sel[1] - mux_out.sel,
+               mux_out.out = out;
+main;
+       connectors:
+               a[4],
+               b[4],
+               op[2],
+               out[4];
+       parts:
+               nand - nand4,
+               nor - nor4,
+               xor - xor4,
+               adder - adder4,
+               mux - mux4x4;
+       connections:
+               a = nand.a,
+               b = nand.b,
+               a = nor.a,
+               b = nor.b,
+               a = xor.a,
+               b = xor.b,
+               a = adder.a,
+               b = adder.b,
+               off - adder.carry_in,
+               nand.out = mux.a,
+               nor.out = mux.b,
+               xor.out = mux.c,
+               adder.out = mux.d,
+               op = mux.sel,
+               mux.out = out;
index a1488d87336bceb8dec6a322998d1d390d92d68d..64142e8531e8e94b94662e1dac18c82c3d140a70 100644 (file)
@@ -126,7 +126,7 @@ char        *string_to_type(const char *str)
        while (state < state_count)
        {
                if (!ft_strcmp(str, g_node_state_strings[state]))
-                       return (ft_strdup(g_defined_tokens[state].type));
+                       return (ft_strdup(g_defined_tokens[node_state].type));
                ++state;
        }
        return (ft_strdup(g_defined_tokens[string].type));
@@ -195,6 +195,7 @@ int tokenize(t_vec *tokens, int fd)
                        else
                        {
                                free(line);
+                               free_token(&info_token);
                                ft_vec_free(tokens, free_token_void);
                                return (1);
                        }
@@ -211,7 +212,10 @@ int        tokenize(t_vec *tokens, int fd)
                free(tmp);
                tmp = get_next_line(fd);
                if (!tmp)
+               {
+                       free(line);
                        break;
+               }
                ft_strcat_alloc(&line, tmp);
                free(tmp);
        }
@@ -255,6 +259,18 @@ int        cmp_strings_void(const void *a_v, const void *b_v)
        return (ft_strcmp(*a, *b));
 }
 
+typedef union u_raw_pinbus
+{
+       t_id    pin;
+       t_vec   bus;
+}                      t_raw_pinbus;
+
+typedef struct s_pinbus
+{
+       int                             is_pin;
+       t_raw_pinbus    pinbus;
+}                                      t_pinbus;
+
 int    init_new_part(t_part *part)
 {
        t_ft_stat       res;
@@ -262,7 +278,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->name_to_node, sizeof(char *), sizeof(t_node *), cmp_strings_void);
+       res = res || ft_dict_init(&part->name_to_node, sizeof(char *), sizeof(t_pinbus), cmp_strings_void);
        res = res || ft_dict_init(&part->used_parts, sizeof(char *), sizeof(t_part_spec), cmp_strings_void);
        return (res != success);
 }
@@ -276,6 +292,17 @@ void       free_string_void(void *string_v)
        return ;
 }
 
+void   free_pinbus_void(void *pinbus_v)
+{
+       t_pinbus        *pinbus;
+
+       pinbus = pinbus_v;
+       if (pinbus->is_pin)
+               return ;
+       ft_vec_free(&pinbus->pinbus.bus, NULL);
+       return ;
+}
+
 void   free_part(t_part *part)
 {
        if (!part)
@@ -284,7 +311,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->name_to_node, free_string_void, NULL);
+       ft_dict_free(&part->name_to_node, free_string_void, free_pinbus_void);
        return ;
 }
 
@@ -302,7 +329,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->name_to_node, free_string_void, NULL);
+       ft_dict_free(&part->name_to_node, free_string_void, free_pinbus_void);
        return ;
 }
 
@@ -365,6 +392,7 @@ int extract_used_names(t_catalog *part_catalog, t_parse_tree_node *part_spec_lis
        if (!new_part.name)
                return (1);
        used_parts = ft_cget_child_deep(new_part.parsed_node, 2, 2, 1);
+       res = 0;
        while (used_parts->children.size == 3)
        {
                res = write_used_part(&new_part, ft_cget_node_child(used_parts, 2));
@@ -414,7 +442,7 @@ static const char                   g_p_name[] = "p";
 static const char                      g_n_name[] = "n";
 
 // IO needs to hold node id instead of pointer
-#define G_SIZE_OF_IO_NODE (sizeof(t_rbtree_node) + sizeof(char *) + sizeof(t_id))
+#define G_SIZE_OF_IO_NODE (sizeof(t_rbtree_node) + sizeof(char *) + sizeof(t_pinbus))
 #define G_COMPLETE_SIZE_OF_FET_PART (sizeof(t_part) + 3 * (sizeof(t_node)) + sizeof(t_id) + sizeof(t_mosfet) + 3 * G_SIZE_OF_IO_NODE)
 
 void   init_fet_nodes(t_part *fet, t_node *nodes, t_id *mosfet)
@@ -455,14 +483,17 @@ void      init_fet_mosfet(t_part *fet, t_mosfet *mosfet, t_type type)
 void   init_fet_single_io(t_part *fet, t_rbtree_node *io_node, t_node *node, t_terminal terminal)
 {
        t_mosfet        *mosfet;
+       t_pinbus        pinbus;
 
-       mosfet = node->connected.vec;
+       pinbus.is_pin = 1;
+       pinbus.pinbus.pin = node->id;
+       mosfet = ft_vec_access(&fet->mosfets, 0);
        io_node->tree = &fet->name_to_node.tree;
        io_node->parent = NULL;
        io_node->is_black = 1;
        io_node->left = NULL;
        io_node->right = NULL;
-       ft_memcpy((char *)&io_node->data + sizeof(char *), &node->id, sizeof(t_id));
+       ft_memcpy((char *)&io_node->data + sizeof(char *), &pinbus, sizeof(t_pinbus));
        if (terminal == source)
        {
                bind_fet_node(&fet->nodes, mosfet, node, source);
@@ -498,7 +529,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->name_to_node, sizeof(char *), sizeof(t_id), cmp_strings_void);
+       ft_dict_init(&fet->name_to_node, sizeof(char *), sizeof(t_pinbus), 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);
@@ -527,6 +558,8 @@ void        initialize_fet_part(t_part *fet, t_type type)
        init_fet_nodes(fet, nodes, mosfet_id);
        init_fet_mosfet(fet, mosfet, type);
        init_fet_io(fet, io_nodes);
+       fet->is_graph_built = 1;
+       return ;
 }
 
 t_part *get_part_from_name(t_catalog *parts_catalog, const char *part_name)
@@ -593,8 +626,9 @@ int rebind_names_to_parts(t_catalog *parts_catalog)
 
 int    add_pin(t_part *part, const char *name)
 {
-       t_node  *node;
-       char    *name_copy;
+       t_node          *node;
+       char            *name_copy;
+       t_pinbus        pin;
 
        node = add_node(&part->nodes, floating);
        if (!node)
@@ -602,7 +636,9 @@ int add_pin(t_part *part, const char *name)
        name_copy = ft_strdup(name);
        if (!name_copy)
                return (1);
-       if (ft_dict_insert(&part->name_to_node, &name_copy, &node->id) != success)
+       pin.is_pin = 1;
+       pin.pinbus.pin = node->id;
+       if (ft_dict_insert(&part->name_to_node, &name_copy, &pin) != success)
        {
                free(name_copy);
                return (1);
@@ -610,64 +646,47 @@ int       add_pin(t_part *part, const char *name)
        return (0);
 }
 
-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[size] = '0' + index % 10;
-               index /= 10;
-               --size;
-       }
-       return ;
-}
-
-static const char      g_bus_index_separator[] = "-";
-
 int    add_bus(t_part *part, const t_parse_tree_node *bus_spec)
 {
-       const char *const       bus_name = ft_cget_child_deep(bus_spec, 3, 0, 0, 0)->token.str;
        const char *const       bus_size_str = ft_cget_child_deep(bus_spec, 2, 2, 0)->token.str;
+       char                            *name;
        size_t                          bus_size;
-       char                            *buffer;
-       size_t                          buffer_size;
-       size_t                          base_size;
+       t_pinbus                        bus;
+       t_node                          *node;
 
        bus_size = (size_t)ft_atoi(bus_size_str);
-       buffer = ft_itoa((int)bus_size);
-       if (!buffer || ft_strcmp(buffer, bus_size_str))
+       name = ft_itoa((int)bus_size);
+       if (!name || ft_strcmp(name, bus_size_str))
        {
-               free(buffer);
+               free(name);
                return (1);
        }
-       free(buffer);
-       base_size = ft_strlen(bus_name) + ft_strlen(g_bus_index_separator);
-       buffer_size = base_size + ft_strlen(bus_size_str) + 1;
-       buffer = malloc(buffer_size);
-       if (!buffer)
+       free(name);
+       ft_vec_init(&bus.pinbus.bus, sizeof(t_id));
+       if (ft_vec_reserve(&bus.pinbus.bus, bus_size) != success)
                return (1);
+       bus.is_pin = 0;
        while (bus_size > 0)
        {
-               --bus_size;
-               ft_strlcpy(buffer, bus_name, buffer_size);
-               ft_strlcat(buffer, g_bus_index_separator, buffer_size);
-               fill_index(buffer + base_size, bus_size);
-               if (add_pin(part, buffer))
+               node = add_node(&part->nodes, floating);
+               if (!node || ft_vec_append(&bus.pinbus.bus, &node->id) != success)
                {
-                       free(buffer);
+                       ft_vec_free(&bus.pinbus.bus, NULL);
                        return (1);
                }
+               --bus_size;
+       }
+       name = ft_strdup(ft_cget_child_deep(bus_spec, 3, 0, 0, 0)->token.str);
+       if (!name)
+       {
+               ft_vec_free(&bus.pinbus.bus, NULL);
+               return (1);
+       }
+       if (ft_dict_insert(&part->name_to_node, &name, &bus) != success)
+       {
+               ft_vec_free(&bus.pinbus.bus, NULL);
+               free(name);
+               return (1);
        }
        return (0);
 }
@@ -700,7 +719,7 @@ int cmp_ids_void(const void *a_v, const void *b_v)
 
        a = a_v;
        b = b_v;
-       return ((a > b) - (a < b));
+       return ((*a > *b) - (*a < *b));
 }
 
 t_ft_stat      copy_id_void(void *dest_v, const void *src_v)
@@ -760,21 +779,21 @@ int       copy_graph(t_part *main_part, t_part *used_part, t_dict *used_to_main_ids)
                *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->connected_gates, &used_node->connected_gates, 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);
+                       *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);
+                       *id = *(t_id *)ft_dict_access(used_to_main_ids, id);
                        ++j;
                }
                ++i;
@@ -799,8 +818,10 @@ int        record_used_io(t_part *main_part, t_part *used_part, const char *used_part_n
        t_dict_entry            dict_entry;
        size_t                          name_size;
        char                            *name;
-       char                            *pin_name;
-       t_id                            id;
+       char                            *pinbus_name;
+       size_t                          i;
+       t_pinbus                        pinbus;
+       t_id                            *id;
 
        if (ft_dict_traversal_init(&named_nodes, &used_part->name_to_node) != success)
                return (1);
@@ -808,16 +829,36 @@ int       record_used_io(t_part *main_part, t_part *used_part, const char *used_part_n
        while (dict_entry.key)
        {
                name = *(char **)dict_entry.key;
-               id = *(t_id *)dict_entry.el;
+               pinbus = *(t_pinbus *)dict_entry.el;
                if (ft_strchr(name, *g_part_name_separator))
+               {
+                       dict_entry = ft_dict_traverse_full(&named_nodes);
                        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))
+               pinbus_name = malloc(name_size);
+               ft_strlcpy(pinbus_name, used_part_name, name_size);
+               ft_strlcat(pinbus_name, g_part_name_separator, name_size);
+               ft_strlcat(pinbus_name, name, name_size);
+               if (pinbus.is_pin)
+                       pinbus.pinbus.pin = *(t_id *)ft_dict_access(used_to_main_ids, &pinbus.pinbus.pin);
+               else
+               {
+                       if (ft_vec_copy(&pinbus.pinbus.bus, &((t_pinbus *)dict_entry.el)->pinbus.bus,
+                                       copy_id_void, NULL) != success)
+                       {
+                               ft_dict_traversal_free(&named_nodes);
+                               return (1);
+                       }
+                       i = 0;
+                       while (i < pinbus.pinbus.bus.size)
+                       {
+                               id = ft_vec_access(&pinbus.pinbus.bus, i);
+                               *id = *(t_id *)ft_dict_access(used_to_main_ids, id);
+                               ++i;
+                       }
+               }
+               if (ft_dict_insert(&main_part->name_to_node, &pinbus_name, &pinbus))
                {
                        ft_dict_traversal_free(&named_nodes);
                        return (1);
@@ -905,76 +946,199 @@ t_state  parsed_node_to_state(const t_parse_tree_node *state_node)
        return (unknown);
 }
 
-char   *get_pin_name(const t_parse_tree_node *pin_spec)
+char   *get_pinbus_name(const t_parse_tree_node *pinbus_spec)
 {
+       size_t                                  size;
        const char                              *part_name;
-       const char                              *pin_name;
-       const char                              *index;
+       const char                              *pinbus_name;
        char                                    *whole_name;
        const t_parse_tree_node *helper_node;
 
-       if (pin_spec->children.size == 1)
+       if (pinbus_spec->children.size == 1)
        {
                part_name = NULL;
-               helper_node = ft_cget_node_child(pin_spec, 0);
+               helper_node = ft_cget_node_child(pinbus_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);
+               part_name = ft_cget_child_deep(pinbus_spec, 3, 0, 0, 0)->token.str;
+               helper_node = ft_cget_node_child(pinbus_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;
+       pinbus_name = ft_cget_child_deep(helper_node, 3, 0, 0, 0)->token.str;
+       size = ft_strlen(part_name) + (part_name != NULL) * ft_strlen(g_part_name_separator)
+               + ft_strlen(pinbus_name) + 1;
        whole_name = malloc(size);
+       if (!whole_name)
+               return (NULL);
        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);
-       }
+       ft_strlcat(whole_name, pinbus_name, size);
        return (whole_name);
 }
 
-int    set_pin_state(t_part *part, const t_parse_tree_node *pin_spec, t_state state)
+t_pinbus       *get_pinbus_from_spec(t_part *part, const t_parse_tree_node *pinbus_spec)
 {
-       char    *name;
-       t_id    id;
+       char            *name;
+       t_pinbus        *pinbus;
 
-       name = get_pin_name(pin_spec);
+       name = get_pinbus_name(pinbus_spec);
        if (!name)
-               return (1);
-       id = *(t_id *)ft_dict_access(&part->name_to_node, name);
+               return (NULL);
+       pinbus = ft_dict_access(&part->name_to_node, &name);
        free(name);
+       return (pinbus);
+}
+
+int    set_pin_state(t_part *part, const t_parse_tree_node *pin_spec, t_state state)
+{
+       size_t                  index;
+       const t_pinbus  *pinbus;
+       t_id                    id;
+
+       pinbus = get_pinbus_from_spec(part, pin_spec);
+       if (!pinbus)
+               return (1);
+       if (pinbus->is_pin)
+               id = pinbus->pinbus.pin;
+       else
+       {
+               index = (size_t)ft_atoi(ft_cget_child_deep(pin_spec, 3, (int)pin_spec->children.size - 1, 1, 1)->token.str);
+               if (index >= pinbus->pinbus.bus.size)
+                       return (1);
+               id = *(const t_id *)ft_vec_caccess(&pinbus->pinbus.bus, index);
+       }
        get_node_by_id(&part->nodes, id)->set_state = state;
        return (0);
 }
 
+int    get_subbus_indeces(const t_pinbus *pinbus, const t_parse_tree_node *bus_pinbus_spec, size_t *first, size_t *last)
+{
+       const t_parse_tree_node *part_bus_pinbus_spec;
+
+       part_bus_pinbus_spec = ft_cget_node_child(bus_pinbus_spec, bus_pinbus_spec->children.size - 1);
+       if (part_bus_pinbus_spec->children.size == 1)
+       {
+               *first = 0;
+               if (!last)
+                       return (1);
+               *last = pinbus->pinbus.bus.size - 1;
+       }
+       else
+       {
+               *first = (size_t)ft_atoi(ft_cget_child_deep(part_bus_pinbus_spec, 3, 1, 1, 0)->token.str);
+               if (*first >= pinbus->pinbus.bus.size)
+                       return (1);
+               if (last)
+               {
+                       *last = (size_t)ft_atoi(ft_cget_child_deep(part_bus_pinbus_spec, 3, 1, 3, 0)->token.str);
+                       if (*last >= pinbus->pinbus.bus.size)
+                               return (1);
+               }
+       }
+       return (0);
+}
+
+void   swap_indeces(size_t *a, size_t *b)
+{
+       size_t  tmp;
+
+       tmp = *a;
+       *a = *b;
+       *b = tmp;
+       return ;
+}
+
 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;
+       const t_pinbus                  *pinbus;
 
-       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)
+       pinbus = get_pinbus_from_spec(part, bus_spec);
+       if (!pinbus
+               || get_subbus_indeces(pinbus, bus_spec, &i, &last_index))
+               return (1);
+       if (i > last_index)
+               swap_indeces(&i, &last_index);
+       while (i <= last_index)
+       {
+               get_node_by_id(&part->nodes,
+                               *(const t_id *)ft_vec_caccess(&pinbus->pinbus.bus, i++))
+                       ->set_state = state;
+       }
+       return (0);
+}
+
+void   remap_bus_ids(t_vec *bus, t_id to, t_id from)
+{
+       size_t  i;
+       t_id    *id;
+
+       i = 0;
+       while (i < bus->size)
+       {
+               id = ft_vec_access(bus, i);
+               if (*id == from)
+                       *id = to;
+               ++i;
+       }
+       return ;
+}
+
+// to was chosen before from so that the IDs can be given in the same order as merging nodes
+int    remap_ids(t_part *part, t_id to, t_id from)
+{
+       t_dict_traversal        traversal;
+       t_pinbus                        *pinbus;
+
+       if (ft_dict_traversal_init(&traversal, &part->name_to_node) != success)
+               return (1);
+       pinbus = ft_dict_traverse(&traversal);
+       while (pinbus)
+       {
+               if (pinbus->is_pin && pinbus->pinbus.pin == from)
+                       pinbus->pinbus.pin = to;
+               else if (!pinbus->is_pin)
+                       remap_bus_ids(&pinbus->pinbus.bus, to, from);
+               pinbus = ft_dict_traverse(&traversal);
+       }
+       ft_dict_traversal_free(&traversal);
+       return (0);
+}
+
+t_node *tie_bus(t_part *part, const t_parse_tree_node *bus_spec)
+{
+       size_t                          i;
+       size_t                          last_index;
+       t_id                            id;
+       t_pinbus                        *pinbus;
+       t_node                          *base_node;
+       t_node                          *merged_node;
+
+       pinbus = get_pinbus_from_spec(part, bus_spec);
+       if (!pinbus
+               || get_subbus_indeces(pinbus, bus_spec, &i, &last_index))
+               return (NULL);
+       if (i > last_index)
+       {
+               i += last_index;
+               last_index = i - last_index;
+               i -= last_index;
+       }
+       base_node = get_node_by_id(&part->nodes, *(const t_id *)ft_vec_caccess(&pinbus->pinbus.bus, i++));
+       while (i <= last_index)
        {
-               i = 1;
-               last_index = 
+               id = *(t_id *)ft_vec_access(&pinbus->pinbus.bus, i++);
+               merged_node = get_node_by_id(&part->nodes, id);
+               if (merge_nodes(&part->nodes, &part->mosfets, base_node, merged_node))
+                       return (NULL);
+               remap_ids(part, base_node->id, id);
+       }
+       return (base_node);
 }
 
 int    set_state_from_connection(t_part *part, const t_parse_tree_node *connection)
@@ -982,7 +1146,7 @@ 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;
+       t_node                                  *node;
 
        helper_node = ft_cget_node_child(connection, 0);
        if (!ft_strcmp(helper_node->token.type, g_defined_tokens[node_state].type))
@@ -997,13 +1161,131 @@ int     set_state_from_connection(t_part *part, const t_parse_tree_node *connection)
                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)
+       node = tie_bus(part, helper_node);
+       if (!node)
                return (1);
-       get_node_by_id(&part->nodes, id)->set_state = state;
+       node->set_state = state;
        return (0);
 }
 
+t_node *get_node_from_spec(t_part *part, const t_parse_tree_node *pin_spec)
+{
+       size_t          index;
+       t_id            id;
+       t_pinbus        *pinbus;
+
+       pinbus = get_pinbus_from_spec(part, pin_spec);
+       if (!pinbus)
+               return (NULL);
+       if (pinbus->is_pin)
+               id = pinbus->pinbus.pin;
+       else
+       {
+               if (get_subbus_indeces(pinbus, pin_spec, &index, NULL))
+                       return (NULL);
+               id = *(t_id *)ft_vec_access(&pinbus->pinbus.bus, index);
+       }
+       if (!id)
+               return (NULL);
+       return (get_node_by_id(&part->nodes, id));
+}
+
+int    add_pin_pin_connection(t_part *part, const t_parse_tree_node *connection)
+{
+       t_node          *node1;
+       t_node          *node2;
+
+       node1 = get_node_from_spec(part, ft_cget_node_child(connection, 0));
+       node2 = get_node_from_spec(part, ft_cget_node_child(connection, 2));
+       if (!node1 || !node2)
+               return (1);
+       remap_ids(part, node1->id, node2->id);
+       return (merge_nodes(&part->nodes, &part->mosfets, node1, node2));
+}
+
+int    connect_bus_pin(t_part *part, t_pinbus *pinbuses[2], size_t indexes[2])
+{
+       t_id    id;
+       t_node  *nodes[2];
+
+       id = *(t_id *)ft_vec_access(&pinbuses[0]->pinbus.bus, indexes[0]);
+       nodes[0] = get_node_by_id(&part->nodes, id);
+       id = *(t_id *)ft_vec_access(&pinbuses[1]->pinbus.bus, indexes[1]);
+       nodes[1] = get_node_by_id(&part->nodes, id);
+       if (!nodes[0] || !nodes[1])
+               return (1);
+       remap_ids(part, nodes[0]->id, nodes[1]->id);
+       return (merge_nodes(&part->nodes, &part->mosfets, nodes[0], nodes[1]));
+}
+
+int    add_bus_bus_connection(t_part *part, const t_parse_tree_node *connection)
+{
+       size_t          start_bounds[2];
+       size_t          end_bounds[2];
+       t_pinbus        *pinbuses[2];
+
+       pinbuses[0] = get_pinbus_from_spec(part, ft_cget_node_child(connection, 0)); 
+       pinbuses[1] = get_pinbus_from_spec(part, ft_cget_node_child(connection, 2)); 
+       if (get_subbus_indeces(pinbuses[0], ft_cget_node_child(connection, 0), &start_bounds[0], &end_bounds[0])
+               || get_subbus_indeces(pinbuses[1], ft_cget_node_child(connection, 2), &start_bounds[1], &end_bounds[1]))
+               return (1);
+       if (start_bounds[0] >= end_bounds[0])
+       {
+               swap_indeces(&start_bounds[0], &end_bounds[0]);
+               swap_indeces(&start_bounds[1], &end_bounds[1]);
+       }
+       if (start_bounds[1] <= end_bounds[1])
+       {
+               if (end_bounds[0] - start_bounds[0] != end_bounds[1] - start_bounds[1])
+                       return (1);
+               while (start_bounds[0] <= end_bounds[0])
+               {
+                       if (connect_bus_pin(part, pinbuses, start_bounds))
+                               return (1);
+                       ++start_bounds[0];
+                       ++start_bounds[1];
+               }
+       }
+       else
+       {
+               if (end_bounds[0] - start_bounds[0] != start_bounds[1] - end_bounds[1])
+                       return (1);
+               while (start_bounds[0] <= end_bounds[0])
+               {
+                       if (connect_bus_pin(part, pinbuses, start_bounds))
+                               return (1);
+                       ++start_bounds[0];
+                       --start_bounds[1];
+               }
+       }
+       return (0);
+}
+
+int    add_pin_bus_connection(t_part *part, const t_parse_tree_node *connection)
+{
+       const t_parse_tree_node *pin_spec;
+       const t_parse_tree_node *bus_spec;
+       t_node                                  *node1;
+       t_node                                  *node2;
+
+       if (!ft_strcmp(ft_cget_node_child(connection, 1)->token.str, g_defined_tokens[widen_sign].str))
+       {
+               pin_spec = ft_cget_node_child(connection, 0);
+               bus_spec = ft_cget_node_child(connection, 2);
+       }
+       else
+       {
+               pin_spec = ft_cget_node_child(connection, 2);
+               bus_spec = ft_cget_node_child(connection, 0);
+       }
+       node1 = tie_bus(part, bus_spec);
+       node2 = get_node_from_spec(part, pin_spec);
+       if (!node1 || !node2)
+               return (1);
+       remap_ids(part, node1->id, node2->id);
+       return (merge_nodes(&part->nodes, &part->mosfets, node1, node2));
+}
+
 int    add_connection(t_part *part, const t_parse_tree_node *connection)
 {
        if (is_state_setting_connection(connection))
@@ -1103,7 +1385,7 @@ int       c_load(WINDOW *command_win, t_input input, t_vec *nodes, t_vec *mosfets)
        }
        parse_tree = ft_parse(&tokens, &parsing_table);
        ft_parsing_table_free(&parsing_table);
-       ft_vec_free(&tokens, NULL);
+       ft_vec_free(&tokens, free_token_void);
        if (parse_tree == NULL)
        {
                wprintw(command_win, "Could not parse file\n");
@@ -1111,9 +1393,11 @@ int      c_load(WINDOW *command_win, t_input input, t_vec *nodes, t_vec *mosfets)
        }
        if (rewrite_graph(parse_tree, nodes, mosfets))
        {
+               ft_parse_tree_free(parse_tree);
                wprintw(command_win, "Could not execute file\n");
                return (1);
        }
+       ft_parse_tree_free(parse_tree);
        //rebuild_schema(nodes, mosfets);
        return (1);
 }
index fa2949aa7e9e49d918b39f4cd2421f743d59419d..1f22ba12f9d75c5533a3e0164d4e467676d4eb72 100644 (file)
@@ -28,6 +28,7 @@ void  free_node(void *node)
 {
        ft_vec_free(&((t_node *)node)->connected, NULL);
        ft_vec_free(&((t_node *)node)->connected_gates, NULL);
+       ft_vec_free(&((t_node *)node)->segments, NULL);
        return ;
 }