Support default return value in o_complex_get_refdes.
[geda-gaf/berndj.git] / gnetlist / src / s_traverse.c
blobeab4478090811253cc3d4d0bff1147d0ccb436cc
1 /* gEDA - GPL Electronic Design Automation
2 * gnetlist - gEDA Netlist
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
21 #include <config.h>
23 #include <stdio.h>
24 #ifdef HAVE_STRING_H
25 #include <string.h>
26 #endif
27 #include <math.h>
29 #include <libgeda/libgeda.h>
31 #include "../include/globals.h"
32 #include "../include/prototype.h"
34 #ifdef HAVE_LIBDMALLOC
35 #include <dmalloc.h>
36 #endif
38 void s_traverse_init(void)
40 netlist_head = s_netlist_add(NULL);
41 netlist_head->nlid = -1; /* head node */
43 graphical_netlist_head = s_netlist_add(NULL);
44 graphical_netlist_head->nlid = -1; /* head node */
46 if (verbose_mode) {
47 printf
48 ("\n\n------------------------------------------------------\n");
49 printf("Verbose mode legend\n\n");
50 printf("n : Found net\n");
51 printf("C : Found component (staring to traverse component)\n");
52 printf
53 ("p : Found pin (starting to traverse pin / or examining pin)\n");
54 printf("P : Found end pin connection (end of this net)\n");
55 printf("R : Starting to rename a net\n");
56 printf("v : Found source attribute, traversing down\n");
57 printf("^ : Finished underlying source, going back up\n");
58 printf("u : Found a refdes which needs to be demangle\n");
59 printf
60 ("U : Found a connected_to refdes which needs to be demangle\n");
61 printf
62 ("------------------------------------------------------\n\n");
67 void s_traverse_start(TOPLEVEL * pr_current)
69 GList *iter;
70 PAGE *p_current;
72 for ( iter = geda_list_get_glist( pr_current->pages );
73 iter != NULL;
74 iter = g_list_next( iter ) ) {
76 p_current = (PAGE *)iter->data;
78 /* only traverse pages which are toplevel, ie not underneath */
79 if (p_current->object_head && p_current->page_control == 0) {
80 /* XXX Does this require s_toplevel_goto_page to get the right cwd? */
81 pr_current->page_current = p_current;
82 s_traverse_sheet(pr_current, p_current->object_head, NULL);
86 /* now that all the sheets have been read, go through and do the */
87 /* post processing work */
88 s_netlist_post_process(pr_current, netlist_head);
90 /* Now match the graphical netlist with the net names already assigned */
91 s_netlist_name_named_nets(pr_current, netlist_head,
92 graphical_netlist_head);
94 if (verbose_mode) {
95 printf("\nInternal netlist representation:\n\n");
96 s_netlist_print(netlist_head);
101 void
102 s_traverse_sheet(TOPLEVEL * pr_current, OBJECT *o_current,
103 char *hierarchy_tag)
105 NETLIST *netlist;
106 char *temp;
107 SCM scm_uref;
108 char *temp_uref;
109 gboolean is_graphical=FALSE;
111 if (verbose_mode) {
112 printf("- Starting internal netlist creation\n");
115 while (o_current != NULL) {
116 netlist = s_netlist_return_tail(netlist_head);
118 if (o_current->type == OBJ_PLACEHOLDER) {
119 printf("WARNING: Found a placeholder/missing component, are you missing a symbol file? [%s]\n", o_current->complex_basename);
122 if (o_current->type == OBJ_COMPLEX) {
123 #if DEBUG
124 printf("starting NEW component\n\n");
125 #endif
127 verbose_print(" C");
129 /* look for special tag */
130 temp = o_attrib_search_component(o_current, "graphical");
131 if (temp) {
132 /* traverse graphical elements, but adding them to the
133 graphical netlist */
134 g_free(temp);
136 netlist = s_netlist_return_tail(graphical_netlist_head);
137 is_graphical = TRUE;
139 netlist = s_netlist_add(netlist);
140 netlist->nlid = o_current->sid;
142 scm_uref = g_scm_c_get_uref(pr_current, o_current);
144 if (scm_is_string( scm_uref )) {
145 temp_uref = scm_to_locale_string( scm_uref );
146 netlist->component_uref =
147 s_hierarchy_create_uref(pr_current, temp_uref, hierarchy_tag);
148 g_free(temp_uref);
149 } else {
150 if (hierarchy_tag) {
151 netlist->component_uref = g_strdup (hierarchy_tag);
152 } else {
153 netlist->component_uref = NULL;
157 if (hierarchy_tag) {
158 netlist->hierarchy_tag = g_strdup (hierarchy_tag);
161 netlist->object_ptr = o_current;
163 if (!netlist->component_uref) {
164 /* search of net attribute */
165 /* maybe symbol is not a component */
166 /* but a power / gnd symbol */
167 temp =
168 o_attrib_search_name(o_current->complex->prim_objs,
169 "net", 0);
171 /* nope net attribute not found */
172 if ( (!temp) && (!is_graphical) ) {
173 fprintf(stderr,
174 "Could not find refdes on component and could not find any special attributes!\n");
176 netlist->component_uref = g_strdup("U?");
177 } else {
179 #if DEBUG
180 printf("yeah... found a power symbol\n");
181 #endif
182 /* it's a power or some other special symbol */
183 netlist->component_uref = NULL;
184 g_free(temp);
188 netlist->cpins =
189 s_traverse_component(pr_current, o_current,
190 hierarchy_tag);
192 /* here is where you deal with the */
193 /* net attribute */
194 s_netattrib_handle(pr_current, o_current, netlist,
195 hierarchy_tag);
197 /* now you need to traverse any underlying schematics */
198 if (pr_current->hierarchy_traversal == TRUE) {
199 s_hierarchy_traverse(pr_current, o_current, netlist);
203 o_current = o_current->next;
206 verbose_done();
209 CPINLIST *s_traverse_component(TOPLEVEL * pr_current, OBJECT * component,
210 char *hierarchy_tag)
212 CPINLIST *cpinlist_head = NULL;
213 CPINLIST *cpins = NULL;
214 OBJECT *o_current = NULL;
215 NET *nets_head = NULL;
216 NET *nets = NULL;
217 char *temp;
218 CONN *c_current;
219 GList *cl_current;
221 o_current = component->complex->prim_objs;
223 cpinlist_head = cpins = s_cpinlist_add(NULL);
224 cpins->plid = -1;
226 while (o_current != NULL) {
227 if (o_current->type == OBJ_PIN) {
229 verbose_print("p");
231 o_current->visited = 1;
233 /* add cpin node */
234 cpins = s_cpinlist_add(cpins);
235 cpins->plid = o_current->sid;
237 /* search the object only */
238 cpins->pin_number = o_attrib_search_name_single(o_current, "pinnumber",
239 NULL);
241 temp =
242 o_attrib_search_name_single_count(o_current, "pinlabel",
245 if (temp) {
246 cpins->pin_label = temp;
249 /* head nets node */
250 /* is this really need */
251 nets_head = nets = s_net_add(NULL);
252 nets->nid = -1;
255 cl_current = o_current->conn_list;
256 while (cl_current != NULL) {
258 c_current = (CONN *) cl_current->data;
261 if (c_current->other_object != NULL) {
263 #if DEBUG
264 printf("c_current other_object, not NULL\n");
265 #endif
267 if (!c_current->other_object->visited &&
268 c_current->other_object != o_current) {
270 nets = s_net_add(nets);
271 nets->nid = o_current->sid;
273 nets->connected_to =
274 s_net_return_connected_string(pr_current,
275 o_current,
276 hierarchy_tag);
278 /* net= new */
279 if (strstr(nets->connected_to, "POWER")) {
280 #if DEBUG
281 printf("going to find netname %s\n",
282 nets->connected_to);
283 #endif
284 nets->net_name =
285 s_netattrib_return_netname(pr_current,
286 o_current,
287 nets->
288 connected_to,
289 hierarchy_tag);
290 nets->net_name_has_priority = TRUE;
291 g_free(nets->connected_to);
292 nets->connected_to = NULL;
294 #if DEBUG
295 printf("%s\n", nets->connected_to);
296 #endif
297 nets =
298 s_traverse_net(pr_current, o_current, nets,
299 c_current->other_object,
300 hierarchy_tag);
302 s_traverse_clear_all_visited(pr_current->
303 page_current->object_head);
307 cl_current = g_list_next(cl_current);
310 cpins->nets = nets_head;
311 /* s_net_print(nets); */
313 /* this is iffy */
314 /* should pass in page_current in top level func */
316 s_traverse_clear_all_visited(pr_current->page_current->
317 object_head);
319 o_current = o_current->next;
323 return (cpinlist_head);
327 void s_traverse_clear_all_visited(OBJECT * object_head)
329 OBJECT *o_current;
331 o_current = object_head;
333 while (o_current != NULL) {
335 #if DEBUG
336 if (o_current->visited) {
337 printf("%s\n", o_current->name);
339 #endif
341 o_current->visited = 0;
343 if (o_current->type == OBJ_COMPLEX
344 && o_current->complex->prim_objs) {
345 s_traverse_clear_all_visited(o_current->complex->prim_objs);
348 o_current = o_current->next;
353 NET *s_traverse_net(TOPLEVEL * pr_current, OBJECT * previous_object,
354 NET * nets, OBJECT * object, char *hierarchy_tag)
356 OBJECT *o_current;
357 NET *new_net;
358 CONN *c_current;
359 GList *cl_current;
360 char *temp;
362 o_current = object;
364 new_net = nets = s_net_add(nets);
365 new_net->nid = object->sid;
367 /* pins are not allowed to have the netname attribute attached to them */
368 if (o_current->type != OBJ_PIN) {
369 temp = o_attrib_search_name_single(o_current, "netname", NULL);
371 if (temp) {
372 new_net->net_name =
373 s_hierarchy_create_netname(pr_current, temp,
374 hierarchy_tag);
375 g_free(temp);
376 } else {
378 /* search for the old label= attribute */
379 temp = o_attrib_search_name_single(o_current, "label", NULL);
380 if (temp) {
381 printf("WARNING: Found label=%s. label= is deprecated, please use netname=\n", temp);
382 new_net->net_name =
383 s_hierarchy_create_netname(pr_current, temp,
384 hierarchy_tag);
385 g_free(temp);
389 #if DEBUG
390 printf("inside traverse: %s\n", object->name);
391 #endif
393 if (object->type == OBJ_PIN) {
395 verbose_print("P");
397 new_net->connected_to =
398 s_net_return_connected_string(pr_current, o_current,
399 hierarchy_tag);
401 temp = o_attrib_search_name_single_count(o_current, "pinlabel", 0);
403 if (temp) {
404 new_net->pin_label = temp;
407 /* net= new */
408 if (strstr(nets->connected_to, "POWER")) {
410 #if DEBUG
411 printf("going to find netname %s \n", nets->connected_to);
412 #endif
413 nets->net_name =
414 s_netattrib_return_netname(pr_current, o_current,
415 nets->connected_to,
416 hierarchy_tag);
417 nets->net_name_has_priority = TRUE;
418 g_free(nets->connected_to);
419 nets->connected_to = NULL;
421 #if DEBUG
422 printf("traverse connected_to: %s\n", new_net->connected_to);
423 #endif
424 return (nets);
428 /*printf("Found net %s\n", object->name); */
429 verbose_print("n");
431 object->visited++;
433 /* this is not perfect yet and won't detect a loop... */
434 if (object->visited > 100) {
435 fprintf(stderr, "Found a possible net/pin infinite connection\n");
436 exit(-1);
439 cl_current = object->conn_list;
440 while (cl_current != NULL) {
442 c_current = (CONN *) cl_current->data;
444 if (c_current->other_object != NULL) {
446 #if DEBUG
447 printf("c_current %s visited: %d\n",
448 c_current->other_object->name,
449 c_current->other_object->visited);
450 #endif
452 if (!c_current->other_object->visited &&
453 c_current->other_object != o_current &&
454 c_current->other_object->type != OBJ_BUS) {
456 nets =
457 s_traverse_net(pr_current, object, nets,
458 c_current->other_object, hierarchy_tag);
462 cl_current = g_list_next(cl_current);
465 return (nets);