Fix o_net_consolidate_segments() to consolidate with all joined lines
[geda-gaf/pcjc2.git] / gnetlist / src / s_hierarchy.c
blob8b91719ce744ef1a38343a2e7e9ff9236999f1e4
1 /* gEDA - GPL Electronic Design Automation
2 * gnetlist - gEDA Netlist
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <config.h>
23 #include <stdio.h>
24 #include <math.h>
25 #ifdef HAVE_STRING_H
26 #include <string.h>
27 #endif
28 #ifdef HAVE_STRINGS_H
29 #include <strings.h>
30 #endif
32 #include <libgeda/libgeda.h>
34 #include "../include/globals.h"
35 #include "../include/prototype.h"
36 #include "../include/gettext.h"
38 #ifdef HAVE_LIBDMALLOC
39 #include <dmalloc.h>
40 #endif
42 void
43 s_hierarchy_traverse(TOPLEVEL * pr_current, OBJECT * o_current,
44 NETLIST * netlist)
46 char *attrib;
47 int page_control=-1;
48 PAGE *p_current;
49 PAGE *child_page;
50 int count = 0;
51 int pcount = 0;
52 int looking_inside = FALSE;
53 int loaded_flag = FALSE;
54 char *current_filename;
55 int graphical=FALSE;
57 attrib = o_attrib_search_attached_attribs_by_name (o_current, "source", 0);
59 /* if above is null, then look inside symbol */
60 if (attrib == NULL) {
61 attrib = o_attrib_search_inherited_attribs_by_name (o_current,
62 "source", count);
64 looking_inside = TRUE;
65 #if DEBUG
66 printf("going to look inside now\n");
67 #endif
70 graphical = s_hierarchy_graphical_search(o_current, count);
71 if (graphical) {
72 /* Do not bother traversing the hierarchy if the symbol has an */
73 /* graphical attribute attached to it. */
74 if (attrib) {
75 g_free(attrib);
76 attrib = NULL;
80 while (attrib) {
82 /* look for source=filename,filename, ... */
83 pcount = 0;
84 current_filename = u_basic_breakup_string(attrib, ',', pcount);
86 /* loop over all filenames */
87 while (current_filename != NULL) {
89 s_log_message(_("Going to traverse source [%s]\n"),
90 current_filename);
92 /* guts here */
93 /* guts for a single filename */
94 p_current = pr_current->page_current;
95 #if DEBUG
96 printf("Going down %s\n", current_filename);
97 #endif
98 GError *err = NULL;
99 child_page =
100 s_hierarchy_down_schematic_single(pr_current,
101 current_filename,
102 pr_current->page_current,
103 page_control,
104 HIERARCHY_FORCE_LOAD,
105 &err);
107 if (child_page == NULL) {
108 g_warning (_("Failed to load subcircuit '%s': %s\n"),
109 current_filename, err->message);
110 fprintf(stderr, _("ERROR: Failed to load subcircuit '%s': %s\n"),
111 current_filename, err->message);
112 g_error_free (err);
113 exit (2);
115 } else {
116 page_control = child_page->page_control;
117 s_page_goto (pr_current, child_page);
119 loaded_flag = TRUE;
121 verbose_print("v\n");
122 verbose_reset_index();
124 netlist->composite_component = TRUE;
125 /* can't do the following, don't know why... HACK TODO */
126 /*netlist->hierarchy_tag = u_basic_strdup (netlist->component_uref);*/
127 s_traverse_sheet (pr_current,
128 s_page_objects (pr_current->page_current),
129 netlist->component_uref);
131 verbose_print("^");
134 pr_current->page_current = p_current;
136 g_free(current_filename);
137 pcount++;
138 current_filename = u_basic_breakup_string(attrib, ',', pcount);
141 g_free(attrib);
143 g_free(current_filename);
145 count++;
147 /* continue looking outside first */
148 if (!looking_inside) {
149 attrib =
150 o_attrib_search_attached_attribs_by_name (o_current, "source",
151 count);
154 /* okay we were looking outside and didn't */
155 /* find anything, so now we need to look */
156 /* inside the symbol */
157 if (!looking_inside && attrib == NULL && !loaded_flag) {
158 looking_inside = TRUE;
159 #if DEBUG
160 printf("switching to go to look inside\n");
161 #endif
164 if (looking_inside) {
165 #if DEBUG
166 printf("looking inside\n");
167 #endif
168 attrib =
169 o_attrib_search_inherited_attribs_by_name (o_current,
170 "source", count);
173 graphical = s_hierarchy_graphical_search(o_current, count);
174 if (graphical) {
175 /* Do not bother looking further in the hierarchy if the symbol */
176 /* has an graphical attribute attached to it. */
177 if (attrib) {
178 g_free(attrib);
179 attrib = NULL;
186 void s_hierarchy_post_process(TOPLEVEL * pr_current, NETLIST * head)
188 NETLIST *nl_current;
189 CPINLIST *pl_current;
190 char *source_net_name = NULL;
191 int did_work = FALSE;
193 s_rename_next_set();
195 nl_current = head;
196 while (nl_current != NULL) {
197 if (nl_current->composite_component) {
198 #if DEBUG
199 printf("Found composite %s\n", nl_current->component_uref);
200 #endif
202 if (nl_current->cpins) {
203 pl_current = nl_current->cpins;
205 while (pl_current != NULL) {
207 if (pl_current->plid != -1) {
208 verbose_print("p");
211 if (pl_current->pin_label == NULL
212 && pl_current->plid != -1) {
213 fprintf(stderr,
214 _("Found a pin [%s] on component [%s] which does not have a label!\n"),
215 nl_current->component_uref,
216 pl_current->pin_number);
217 } else if (pl_current->plid != -1) {
219 #if DEBUG
220 printf("# L: %s %s\n", pl_current->pin_number,
221 pl_current->pin_label);
222 #endif
223 /* get source net name, all nets are named already */
224 source_net_name =
225 s_net_name_search(pr_current,
226 pl_current->nets);
227 #if DEBUG
228 printf("name: %s\n", source_net_name);
229 printf("Now we need to search for: %s/%s\n",
230 nl_current->component_uref,
231 pl_current->pin_label);
232 #endif
234 did_work =
235 s_hierarchy_setup_rename(pr_current, head,
236 nl_current->component_uref,
237 pl_current->pin_label,
238 source_net_name);
239 if (!did_work) {
240 fprintf(stderr,
241 _("Missing I/O symbol with refdes [%s] inside schematic for symbol [%s]\n"),
242 pl_current->pin_label,
243 nl_current->component_uref);
247 pl_current = pl_current->next;
251 nl_current = nl_current->next;
254 s_rename_all(pr_current, head);
255 s_hierarchy_remove_compsite_all(head);
259 s_hierarchy_setup_rename(TOPLEVEL * pr_current, NETLIST * head, char *uref,
260 char *label, char *new_name)
262 NETLIST *nl_current;
263 CPINLIST *pl_current;
264 char *wanted_uref = NULL;
265 int did_work = FALSE;
267 /* this is questionable, because I'm not sure if it's exactly the */
268 /* same as the #if 0'ed out line */
269 /* search for the uref which has the name: label/uref (or whatever the */
270 /* hierarchy tag/separator order is) */
271 wanted_uref = s_hierarchy_create_uref(pr_current, label, uref);
273 #if DEBUG
274 printf("label: %s, uref: %s, wanted_uref: %s\n", label, uref,
275 wanted_uref);
276 #endif
278 nl_current = head;
279 while (nl_current != NULL) {
280 if (nl_current->component_uref) {
281 pl_current = nl_current->cpins;
282 if (strcmp(nl_current->component_uref, wanted_uref) == 0) {
283 if (nl_current->cpins) {
284 /* skip over head of special io symbol */
285 pl_current = nl_current->cpins->next;;
286 #if DEBUG
287 printf("net to be renamed: %s\n",
288 pl_current->net_name);
289 printf("%s -> %s\n", pl_current->net_name, new_name);
290 #endif
291 s_rename_add(pl_current->net_name, new_name);
293 #if DEBUG
294 printf("Going to remove %s\n",
295 nl_current->component_uref);
296 #endif
297 s_hierarchy_remove_urefconn(head,
298 nl_current->
299 component_uref);
300 did_work = TRUE;
304 nl_current = nl_current->next;
307 return (did_work);
310 void s_hierarchy_remove_urefconn(NETLIST * head, char *uref_disable)
312 NETLIST *nl_current;
313 CPINLIST *pl_current;
314 NET *n_current;
315 char uref[80], pin[10];
317 nl_current = head;
318 while (nl_current != NULL) {
319 pl_current = nl_current->cpins;
320 while (pl_current != NULL) {
321 n_current = pl_current->nets;
322 while (n_current != NULL) {
323 if (n_current->connected_to != NULL) {
324 sscanf(n_current->connected_to, "%s %s", uref, pin);
325 #if DEBUG
326 printf(" looking at : %s %s\n", uref, pin);
327 #endif
328 if (strcmp(uref_disable, uref) == 0) {
329 #if DEBUG
330 printf("conn disabling %s\n",
331 n_current->connected_to);
332 #endif
333 /* can't do frees, since some names are links */
334 /* g_free(n_current->connected_to);*/
335 n_current->connected_to = NULL;
338 n_current = n_current->next;
341 pl_current = pl_current->next;
344 if (nl_current->component_uref) {
345 if (strcmp(nl_current->component_uref, uref_disable) == 0) {
346 #if DEBUG
347 printf("refdes disabling: %s\n", nl_current->component_uref);
348 #endif
349 /* can't do frees, since some names are links */
350 /*free(nl_current->component_uref); */
351 nl_current->component_uref = NULL;
354 nl_current = nl_current->next;
358 void s_hierarchy_remove_compsite_all(NETLIST * head)
360 NETLIST *nl_current;
362 nl_current = head;
363 while (nl_current != NULL) {
364 if (nl_current->composite_component) {
365 if (nl_current->component_uref != NULL) {
366 s_hierarchy_remove_urefconn(head,
367 nl_current->component_uref);
370 nl_current = nl_current->next;
375 char *s_hierarchy_create_uref(TOPLEVEL * pr_current, char *basename,
376 char *hierarchy_tag)
378 char *return_value = NULL;
380 if (hierarchy_tag) {
381 if (basename) {
383 if (pr_current->hierarchy_uref_separator) {
384 switch (pr_current->hierarchy_uref_order) {
385 case (APPEND):
386 return_value =
387 g_strconcat (hierarchy_tag,
388 pr_current->hierarchy_uref_separator,
389 basename, NULL);
390 break;
391 case (PREPEND):
392 return_value =
393 g_strconcat (basename,
394 pr_current->hierarchy_uref_separator,
395 hierarchy_tag, NULL);
397 break;
399 } else {
400 switch (pr_current->hierarchy_uref_order) {
401 case (APPEND):
402 return_value =
403 g_strconcat (hierarchy_tag, basename, NULL);
404 break;
405 case (PREPEND):
406 return_value =
407 g_strconcat (basename, hierarchy_tag, NULL);
408 break;
412 } else {
413 return_value = NULL;
415 } else {
416 if (basename) {
417 return_value = g_strdup (basename);
418 } else {
419 return_value = NULL;
423 return (return_value);
426 char *s_hierarchy_create_netname(TOPLEVEL * pr_current, char *basename,
427 char *hierarchy_tag)
429 char *return_value = NULL;
431 if (pr_current->hierarchy_netname_mangle == FALSE) {
432 if (basename) {
433 return (g_strdup (basename));
434 } else {
435 return (NULL);
439 if (hierarchy_tag) {
440 if (basename) {
442 if (pr_current->hierarchy_netname_separator) {
443 switch (pr_current->hierarchy_netname_order) {
444 case (APPEND):
445 return_value =
446 g_strconcat (hierarchy_tag,
447 pr_current->hierarchy_netname_separator,
448 basename, NULL);
450 break;
452 case (PREPEND):
453 return_value =
454 g_strconcat (basename,
455 pr_current->hierarchy_netname_separator,
456 hierarchy_tag, NULL);
458 break;
461 } else {
462 switch (pr_current->hierarchy_netname_order) {
463 case (APPEND):
465 return_value =
466 g_strconcat (hierarchy_tag, basename, NULL);
467 break;
468 case (PREPEND):
469 return_value =
470 g_strconcat (basename, hierarchy_tag, NULL);
472 break;
476 } else {
477 return_value = NULL;
479 } else {
480 if (basename) {
481 return_value = g_strdup (basename);
482 } else {
483 return_value = NULL;
487 return (return_value);
490 char *s_hierarchy_create_netattrib(TOPLEVEL * pr_current, char *basename,
491 char *hierarchy_tag)
493 char *return_value = NULL;
495 if (pr_current->hierarchy_netattrib_mangle == FALSE) {
496 if (basename) {
497 return (g_strdup (basename));
498 } else {
499 return (NULL);
503 if (hierarchy_tag) {
504 if (basename) {
506 if (pr_current->hierarchy_netattrib_separator) {
507 switch (pr_current->hierarchy_netattrib_order) {
508 case (APPEND):
509 return_value =
510 g_strconcat (hierarchy_tag,
511 pr_current->hierarchy_netattrib_separator,
512 basename, NULL);
513 break;
514 case (PREPEND):
515 return_value =
516 g_strconcat (basename,
517 pr_current->hierarchy_netattrib_separator,
518 hierarchy_tag, NULL);
520 break;
522 } else {
523 switch (pr_current->hierarchy_netattrib_order) {
524 case (APPEND):
525 return_value =
526 g_strconcat (hierarchy_tag, basename, NULL);
527 break;
528 case (PREPEND):
529 return_value =
530 g_strconcat (basename, hierarchy_tag, NULL);
531 break;
534 } else {
535 return_value = NULL;
537 } else {
538 if (basename) {
539 return_value = g_strdup (basename);
540 } else {
541 return_value = NULL;
545 return (return_value);
548 void
549 s_hierarchy_remove_uref_mangling(TOPLEVEL * pr_current, NETLIST * head)
551 NETLIST *nl_current;
552 CPINLIST *pl_current;
553 NET *n_current;
554 char uref[80], pin[10];
555 char *new_uref = NULL;
556 char *new_connected_to = NULL;
558 nl_current = head;
559 while (nl_current != NULL) {
561 if (nl_current->component_uref) {
562 verbose_print("u");
563 new_uref =
564 s_hierarchy_return_baseuref(pr_current,
565 nl_current->component_uref);
566 g_free(nl_current->component_uref);
567 nl_current->component_uref = new_uref;
570 pl_current = nl_current->cpins;
572 while (pl_current != NULL) {
573 n_current = pl_current->nets;
574 while (n_current != NULL) {
576 if (n_current->connected_to) {
577 verbose_print("U");
578 sscanf(n_current->connected_to, "%s %s", uref, pin);
579 new_uref =
580 s_hierarchy_return_baseuref(pr_current, uref);
581 new_connected_to = g_strdup_printf("%s %s", new_uref, pin);
582 g_free(n_current->connected_to);
583 n_current->connected_to = new_connected_to;
585 n_current = n_current->next;
588 pl_current = pl_current->next;
590 nl_current = nl_current->next;
595 char *s_hierarchy_return_baseuref(TOPLEVEL * pr_current, char *uref)
597 char *return_value = NULL;
598 char *start_of_base = NULL;
599 char *end_of_base = NULL;
601 /* use hierarchy separator */
603 if (uref == NULL) {
604 return (NULL);
606 #if DEBUG
607 printf("Got uref: _%s_\n", uref);
608 #endif
611 if (pr_current->hierarchy_uref_order == APPEND) {
613 start_of_base = strrchr(uref, '/'); /* separator is always '/' */
615 if (start_of_base == NULL) {
616 return (g_strdup (uref));
619 return_value = g_strdup (start_of_base + 1);
621 } else if (pr_current->hierarchy_uref_order == PREPEND) {
623 end_of_base = strchr(uref, '/');
625 if (end_of_base == NULL) {
626 return (g_strdup (uref));
629 return_value = g_strndup(uref, end_of_base - uref);
632 #if DEBUG
633 printf("new uref return_value = %s\n\n\n", return_value);
634 #endif
636 return (return_value);
639 int s_hierarchy_graphical_search (OBJECT* o_current, int count)
641 char *graphical_attrib;
642 graphical_attrib =
643 o_attrib_search_object_attribs_by_name (o_current, "graphical", count);
645 if (graphical_attrib) {
646 g_free (graphical_attrib);
647 return TRUE;
650 return FALSE;