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
29 #include <libgeda/libgeda.h>
31 #include "../include/globals.h"
32 #include "../include/prototype.h"
34 #ifdef HAVE_LIBDMALLOC
40 static TOPLEVEL
*project_current
;
42 void g_set_project_current(TOPLEVEL
* pr_current
)
44 project_current
= pr_current
;
48 SCM
g_scm_c_get_uref (TOPLEVEL
*toplevel
, OBJECT
*object
)
50 SCM func
= scm_variable_ref (scm_c_lookup ("get-uref"));
51 SCM object_smob
= g_make_object_smob (toplevel
, object
);
52 SCM exp
= scm_list_2 (func
, object_smob
);
54 return g_scm_eval_protected (exp
, SCM_UNDEFINED
);
58 /* this function will only return a unique list of packages */
59 SCM
g_get_packages(SCM level
)
64 NETLIST
*nl_current
= NULL
;
66 SCM_ASSERT(scm_is_string (level
), level
, SCM_ARG1
, "gnetlist:get-pins");
68 /* build a hash table */
69 ht
= g_hash_table_new (g_str_hash
, g_str_equal
);
70 for (nl_current
= netlist_head
; nl_current
!= NULL
;
71 nl_current
= nl_current
->next
) {
72 if (nl_current
->component_uref
!= NULL
) {
73 /* add component_uref in the hash table */
74 /* uniqueness of component_uref is guaranteed by the hashtable */
76 if (g_hash_table_lookup (ht
, nl_current
->component_uref
) == NULL
) {
77 g_hash_table_insert (ht
, nl_current
->component_uref
,
78 nl_current
->component_uref
);
79 list
= scm_cons (scm_from_locale_string (nl_current
->component_uref
),
84 g_hash_table_destroy (ht
);
89 /* this function will only return a non unique list of packages */
90 SCM
g_get_non_unique_packages(SCM level
)
94 NETLIST
*nl_current
= NULL
;
96 SCM_ASSERT(scm_is_string (level
), level
, SCM_ARG1
, "gnetlist:get-pins");
98 for (nl_current
= netlist_head
; nl_current
!= NULL
;
99 nl_current
= nl_current
->next
) {
100 if (nl_current
->component_uref
!= NULL
) {
101 list
= scm_cons (scm_from_locale_string (nl_current
->component_uref
),
110 SCM
g_get_pins(SCM uref
)
114 CPINLIST
*pl_current
;
116 SCM_ASSERT(scm_is_string (uref
), uref
, SCM_ARG1
, "gnetlist:get-pins");
118 /* here is where you make it multi page aware */
119 nl_current
= netlist_head
;
121 /* search for the first instance */
122 /* through the entire list */
123 while (nl_current
!= NULL
) {
125 if (nl_current
->component_uref
) {
126 if (strcmp(nl_current
->component_uref
, SCM_STRING_CHARS (uref
)) == 0) {
128 pl_current
= nl_current
->cpins
;
129 while (pl_current
!= NULL
) {
130 if (pl_current
->pin_number
) {
131 list
= scm_cons (scm_from_locale_string (pl_current
->pin_number
),
134 pl_current
= pl_current
->next
;
138 nl_current
= nl_current
->next
;
144 SCM
g_get_all_nets(SCM scm_level
)
149 CPINLIST
*pl_current
;
152 SCM_ASSERT(scm_is_string (scm_level
), scm_level
, SCM_ARG1
,
153 "gnetlist:get-all-nets");
155 nl_current
= netlist_head
;
157 /* walk through the list of components, and through the list
158 * of individual pins on each, adding net names to the list
159 * being careful to ignore duplicates, and unconnected pins
161 while (nl_current
!= NULL
) {
162 pl_current
= nl_current
->cpins
;
163 while (pl_current
!= NULL
) {
164 if (pl_current
->net_name
) {
166 net_name
= pl_current
->net_name
;
167 /* filter off unconnected pins */
168 if (strncmp(net_name
, "unconnected_pin", 15) != 0) {
169 /*printf("Got net: `%s'\n",net_name); */
170 /* add the net name to the list */
172 printf("Got net: `%s'\n", net_name
);
173 printf("pin %s\n", pl_current
->pin_number
);
175 list
= scm_cons (scm_from_locale_string (net_name
),
179 pl_current
= pl_current
->next
;
181 nl_current
= nl_current
->next
;
187 SCM
g_get_all_unique_nets(SCM scm_level
)
193 CPINLIST
*pl_current
;
196 SCM_ASSERT(scm_is_string (scm_level
), scm_level
, SCM_ARG1
,
197 "gnetlist:get-all-unique-nets");
199 nl_current
= netlist_head
;
201 /* walk through the list of components, and through the list
202 * of individual pins on each, adding net names to the list
203 * being careful to ignore duplicates, and unconnected pins
205 while (nl_current
!= NULL
) {
206 pl_current
= nl_current
->cpins
;
207 while (pl_current
!= NULL
) {
208 if (pl_current
->net_name
) {
210 net_name
= pl_current
->net_name
;
211 /* filter off unconnected pins */
212 if (strncmp(net_name
, "unconnected_pin", 15) != 0) {
213 /* add the net name to the list */
214 /*printf("Got net: `%s'\n",net_name); */
216 x
= scm_from_locale_string (net_name
);
217 if (scm_is_false (scm_member (x
, list
))) {
218 list
= scm_cons (x
, list
);
222 pl_current
= pl_current
->next
;
224 nl_current
= nl_current
->next
;
230 /* given a net name, return all connections */
231 SCM
g_get_all_connections(SCM scm_netname
)
236 SCM is_member
= SCM_EOL
;
237 SCM connlist
= SCM_EOL
;
238 SCM pairlist
= SCM_EOL
;
240 CPINLIST
*pl_current
;
242 char *wanted_net_name
;
247 SCM_ASSERT(scm_is_string(scm_netname
), scm_netname
, SCM_ARG1
,
248 "gnetlist:get-all-connections");
250 wanted_net_name
= SCM_STRING_CHARS (scm_netname
);
252 if (wanted_net_name
== NULL
) {
257 nl_current
= netlist_head
;
259 /* walk through the list of components, and through the list
260 * of individual pins on each, adding net names to the list
261 * being careful to ignore duplicates, and unconnected pins
263 while (nl_current
!= NULL
) {
264 pl_current
= nl_current
->cpins
;
265 while (pl_current
!= NULL
) {
266 if (pl_current
->net_name
) {
268 net_name
= pl_current
->net_name
;
269 /* filter off unconnected pins */
270 if (strcmp(net_name
, wanted_net_name
) == 0) {
271 /* add the net name to the list */
274 printf("found net: `%s'\n", net_name
);
277 n_current
= pl_current
->nets
;
278 while (n_current
!= NULL
) {
280 if (n_current
->connected_to
) {
283 pin
= (char *) g_malloc(sizeof(char) *
287 (char *) g_malloc(sizeof(char) *
291 sscanf(n_current
->connected_to
,
294 pairlist
= scm_list_n (scm_from_locale_string (uref
),
295 scm_from_locale_string (pin
),
299 is_member
= scm_member(x
, connlist
);
301 if (scm_is_false (is_member
)) {
302 connlist
= scm_cons (pairlist
, connlist
);
308 n_current
= n_current
->next
;
312 pl_current
= pl_current
->next
;
314 nl_current
= nl_current
->next
;
320 /* Given a uref and a pin number return a list of: */
321 /* (netname (uref pin) (uref pin) ... ) */
322 SCM
g_get_nets(SCM scm_uref
, SCM scm_pin
)
324 SCM outerlist
= SCM_EOL
;
325 SCM pinslist
= SCM_EOL
;
326 SCM pairlist
= SCM_EOL
;
327 NETLIST
*nl_current
= NULL
;
328 CPINLIST
*pl_current
= NULL
;
330 char *wanted_uref
= NULL
;
331 char *wanted_pin
= NULL
;
332 char *net_name
= NULL
;
337 SCM_ASSERT(scm_is_string (scm_uref
), scm_uref
, SCM_ARG1
,
338 "gnetlist:get-nets");
340 SCM_ASSERT(scm_is_string (scm_pin
), scm_pin
, SCM_ARG2
,
341 "gnetlist:get-nets");
344 wanted_uref
= SCM_STRING_CHARS (scm_uref
);
345 wanted_pin
= SCM_STRING_CHARS (scm_pin
);
347 nl_current
= netlist_head
;
349 /* search for the first instance */
350 /* through the entire list */
351 while (nl_current
!= NULL
) {
353 if (nl_current
->component_uref
) {
355 if (strcmp(nl_current
->component_uref
, wanted_uref
) == 0) {
357 pl_current
= nl_current
->cpins
;
358 while (pl_current
!= NULL
) {
360 if (pl_current
->pin_number
) {
361 if (strcmp(pl_current
->pin_number
, wanted_pin
) ==
364 n_current
= pl_current
->nets
;
366 if (pl_current
->net_name
) {
367 net_name
= pl_current
->net_name
;
370 while (n_current
!= NULL
) {
372 if (n_current
->connected_to
) {
375 pin
= (char *) g_malloc(sizeof(char) *
380 (char *) g_malloc(sizeof(char) *
384 sscanf(n_current
->connected_to
,
387 pairlist
= scm_list_n (scm_from_locale_string (uref
),
388 scm_from_locale_string (pin
),
391 pinslist
= scm_cons (pairlist
, pinslist
);
396 n_current
= n_current
->next
;
400 pl_current
= pl_current
->next
;
404 nl_current
= nl_current
->next
;
407 if (net_name
!= NULL
) {
408 outerlist
= scm_cons (scm_from_locale_string (net_name
), pinslist
);
410 outerlist
= scm_cons (scm_from_locale_string ("ERROR_INVALID_PIN"),
412 fprintf(stderr
, "Invalid wanted_pin passed to get-nets [%s]\n",
420 /* Given a uref, Return a list of pairs, each pair contains the name
421 * of the pin, and the name of the net connected to that pin.
423 SCM
g_get_pins_nets(SCM scm_uref
)
425 SCM pinslist
= SCM_EOL
;
426 SCM pairlist
= SCM_EOL
;
427 NETLIST
*nl_current
= NULL
;
428 CPINLIST
*pl_current
= NULL
;
430 char *wanted_uref
= NULL
;
431 char *net_name
= NULL
;
434 SCM_ASSERT(scm_is_string (scm_uref
),
435 scm_uref
, SCM_ARG1
, "gnetlist:get-pins-nets");
437 wanted_uref
= SCM_STRING_CHARS (scm_uref
);
439 /* search for the any instances */
440 /* through the entire list */
441 for (nl_current
= netlist_head
; nl_current
!= NULL
;
442 nl_current
= nl_current
->next
) {
444 /* is there a uref? */
445 if (nl_current
->component_uref
) {
446 /* is it the one we want ? */
447 if (strcmp(nl_current
->component_uref
, wanted_uref
) == 0) {
449 for (pl_current
= nl_current
->cpins
; pl_current
!= NULL
;
450 pl_current
= pl_current
->next
) {
451 /* is there a valid pin number and a valid name ? */
452 if (pl_current
->pin_number
) {
453 if (pl_current
->net_name
) {
454 /* yes, add it to the list */
455 pin
= pl_current
->pin_number
;
456 net_name
= pl_current
->net_name
;
458 pairlist
= scm_cons (scm_from_locale_string (pin
),
459 scm_from_locale_string (net_name
));
460 pinslist
= scm_cons (pairlist
, pinslist
);
469 pinslist
= scm_reverse (pinslist
); /* pins are in reverse order on the way
476 /*! \brief Get attribute value(s) from a package with given uref.
477 * \par Function Description
478 * This function returns the values of a specific attribute type
479 * attached to the symbol instances with the given refdes.
481 * Every first attribute value found is added to the return list. A
482 * Scheme false value is added if the instance has no such attribute.
484 * \note The order of the values in the return list is the order of
485 * symbol instances within gnetlist (the first element is the value
486 * associated with the first symbol instance).
488 * \param [in] scm_uref Package reference.
489 * \param [in] scm_wanted_attrib Attribute name.
490 * \return A list of attribute values as strings and #f.
492 SCM
g_get_all_package_attributes(SCM scm_uref
, SCM scm_wanted_attrib
)
499 SCM_ASSERT(scm_is_string (scm_uref
),
500 scm_uref
, SCM_ARG1
, "gnetlist:get-all-package-attributes");
502 SCM_ASSERT(scm_is_string (scm_wanted_attrib
),
503 scm_wanted_attrib
, SCM_ARG2
, "gnetlist:get-all-package-attributes");
505 uref
= scm_to_locale_string (scm_uref
);
506 wanted_attrib
= scm_to_locale_string (scm_wanted_attrib
);
508 /* here is where you make it multi page aware */
509 nl_current
= netlist_head
;
511 /* search for uref instances and through the entire list */
512 while (nl_current
!= NULL
) {
514 if (nl_current
->component_uref
) {
515 if (strcmp(nl_current
->component_uref
, uref
) == 0) {
517 o_attrib_search_object_attribs_by_name (nl_current
->object_ptr
,
520 ret
= scm_cons (value
? scm_from_locale_string (value
) : SCM_BOOL_F
, ret
);
525 nl_current
= nl_current
->next
;
529 free (wanted_attrib
);
531 return scm_reverse_x (ret
, SCM_EOL
);
534 /* takes a uref and pinseq number and returns wanted_attribute associated */
535 /* with that pinseq pin and component */
536 SCM
g_get_attribute_by_pinseq(SCM scm_uref
, SCM scm_pinseq
,
537 SCM scm_wanted_attrib
)
539 SCM scm_return_value
;
544 char *return_value
= NULL
;
545 OBJECT
*o_pin_object
;
547 SCM_ASSERT(scm_is_string (scm_uref
),
548 scm_uref
, SCM_ARG1
, "gnetlist:get-pin-number-seq");
550 SCM_ASSERT(scm_is_string (scm_pinseq
),
551 scm_pinseq
, SCM_ARG2
, "gnetlist:get-pin-number-seq");
554 SCM_ASSERT(scm_is_string (scm_wanted_attrib
),
555 scm_wanted_attrib
, SCM_ARG3
, "gnetlist:get-pin-attribute-seq");
557 uref
= SCM_STRING_CHARS (scm_uref
);
558 pinseq
= SCM_STRING_CHARS (scm_pinseq
);
559 wanted_attrib
= SCM_STRING_CHARS (scm_wanted_attrib
);
562 printf("gnetlist:g_netlist.c:g_get_attribute_by_pinseq -- \n");
563 printf(" wanted uref = %s\n", uref
);
564 printf(" wanted_pin_seq = %s\n", pinseq
);
565 printf(" wanted_attrib = %s\n", wanted_attrib
);
568 /* here is where you make it multi page aware */
569 nl_current
= netlist_head
;
571 /* search for the first instance */
572 /* through the entire list */
573 while (nl_current
!= NULL
) {
575 if (nl_current
->component_uref
) {
576 if (strcmp(nl_current
->component_uref
, uref
) == 0) {
578 o_pin_object
= o_complex_find_pin_by_attribute (nl_current
->object_ptr
,
583 o_attrib_search_object_attribs_by_name (o_pin_object
,
590 /* Don't break until we search the whole netlist to handle slotted */
591 /* parts. 4.28.2007 -- SDB. */
594 nl_current
= nl_current
->next
;
598 scm_return_value
= scm_from_locale_string (return_value
);
600 scm_return_value
= scm_from_locale_string ("unknown");
604 printf("gnetlist:g_netlist.c:g_get_attribute_by_pinseq -- ");
605 printf("return_value: %s\n", return_value
);
608 return (scm_return_value
);
611 /* this takes a pin number and returns the appropriate attribute on that pin*/
612 /* scm_pin is the value associated with the pinnumber= attribute and uref */
613 SCM
g_get_attribute_by_pinnumber(SCM scm_uref
, SCM scm_pin
, SCM
616 SCM scm_return_value
;
622 char *return_value
= NULL
;
625 SCM_ASSERT(scm_is_string (scm_uref
),
626 scm_uref
, SCM_ARG1
, "gnetlist:get-pin-attribute");
628 SCM_ASSERT(scm_is_string (scm_pin
),
629 scm_pin
, SCM_ARG2
, "gnetlist:get-pin-attribute");
631 SCM_ASSERT(scm_is_string (scm_wanted_attrib
),
632 scm_wanted_attrib
, SCM_ARG3
, "gnetlist:get-pin-attribute");
634 uref
= SCM_STRING_CHARS (scm_uref
);
635 pin
= SCM_STRING_CHARS (scm_pin
);
636 wanted_attrib
= SCM_STRING_CHARS (scm_wanted_attrib
);
638 /* here is where you make it multi page aware */
639 nl_current
= netlist_head
;
641 /* search for the first instance */
642 /* through the entire list */
643 while (nl_current
!= NULL
&& !done
) {
644 if (nl_current
->component_uref
) {
645 if (strcmp(nl_current
->component_uref
, uref
) == 0) {
648 o_complex_find_pin_by_attribute (nl_current
->object_ptr
,
653 /* only look for the first occurance of wanted_attrib */
655 o_attrib_search_object_attribs_by_name (pin_object
,
659 printf("GOT IT: %s\n", return_value
);
662 } else if (strcmp("pintype",
663 wanted_attrib
) == 0) {
664 if (nl_current
->cpins
) {
665 CPINLIST
*pinobject
=
666 s_cpinlist_search_pin(nl_current
->cpins
, pin
);
671 printf("Supplied pintype 'pwr' for artificial pin '%s' of '%s'\n",
679 nl_current
= nl_current
->next
;
683 scm_return_value
= scm_from_locale_string (return_value
);
685 scm_return_value
= scm_from_locale_string ("unknown");
688 return (scm_return_value
);
692 /* returns value of attribute otherwise string "none" */
693 /* still highly temp and doesn't work right */
694 SCM
g_get_toplevel_attribute(SCM scm_wanted_attrib
)
699 char *attrib_value
= NULL
;
700 SCM scm_return_value
;
702 SCM_ASSERT(scm_is_string (scm_wanted_attrib
),
703 scm_wanted_attrib
, SCM_ARG1
, "gnetlist:get-toplevel-attribute");
705 wanted_attrib
= SCM_STRING_CHARS (scm_wanted_attrib
);
707 for (p_iter
= geda_list_get_glist (project_current
->pages
); p_iter
!= NULL
;
708 p_iter
= g_list_next (p_iter
)) {
709 p_current
= p_iter
->data
;
711 /* only look for first occurrance of the attribute on each page */
713 o_attrib_search_floating_attribs_by_name (s_page_objects (p_current
),
716 /* Stop when we find the first one */
717 if (attrib_value
!= NULL
)
721 if (attrib_value
!= NULL
) {
722 scm_return_value
= scm_from_locale_string (attrib_value
);
723 g_free (attrib_value
);
725 scm_return_value
= scm_from_locale_string ("not found");
728 return (scm_return_value
);
732 /*! \brief Obtain a list of `-O' backend arguments.
733 * \par Function Description
734 * Returns a list of arguments passed to the gnetlist backend via the
735 * `-O' gnetlist command-line option.
738 g_get_backend_arguments()
740 SCM result
= SCM_EOL
;
743 for (iter
= backend_params
; iter
!= NULL
; iter
= g_slist_next (iter
)) {
744 result
= scm_cons (scm_from_locale_string ((char *) iter
->data
),
748 return scm_reverse_x (result
, SCM_UNDEFINED
);
752 /*! \brief Get input files from command line.
753 * \par Function Description
754 * This function returns a list of the files named on the command line.
756 * \return A list of filenames as strings.
758 SCM
g_get_input_files()
761 GSList
*current
= input_files
;
763 while (current
!= NULL
) {
764 list
= scm_cons (scm_from_locale_string (current
->data
), list
);
765 current
= g_slist_next(current
);
768 return scm_reverse_x (list
, SCM_EOL
);
772 /* given a net name, an attribute, and a wanted attribute, return all
773 the given attribute of all the graphical objects connected to that
775 SCM
g_graphical_objs_in_net_with_attrib_get_attrib (SCM scm_netname
, SCM scm_has_attribute
, SCM scm_wanted_attribute
)
780 CPINLIST
*pl_current
;
781 char *wanted_net_name
;
785 char *attrib_value
=NULL
;
786 char *has_attrib_value
= NULL
;
787 char *has_attrib_name
= NULL
;
789 SCM_ASSERT(scm_is_string (scm_netname
), scm_netname
, SCM_ARG1
,
790 "gnetlist:get-attr-of-conn-graph-objs-with-attr");
792 SCM_ASSERT(scm_is_string (scm_wanted_attribute
),
793 scm_wanted_attribute
, SCM_ARG2
,
794 "gnetlist:get-attr-of-conn-graph-objs-with-attr");
796 SCM_ASSERT(scm_is_string (scm_has_attribute
),
797 scm_has_attribute
, SCM_ARG3
,
798 "gnetlist:get-attr-of-conn-graph-objs-with-attr");
800 wanted_net_name
= SCM_STRING_CHARS (scm_netname
);
801 wanted_attrib
= SCM_STRING_CHARS (scm_wanted_attribute
);
802 has_attrib
= SCM_STRING_CHARS (scm_has_attribute
);
804 if (wanted_net_name
== NULL
) {
809 nl_current
= graphical_netlist_head
;
811 /* walk through the list of components, and through the list
812 * of individual pins on each, adding net names to the list
813 * being careful to ignore duplicates, and unconnected pins
815 while (nl_current
!= NULL
) {
816 pl_current
= nl_current
->cpins
;
817 while (pl_current
!= NULL
) {
818 if (pl_current
->net_name
) {
819 net_name
= pl_current
->net_name
;
820 if (strcmp(net_name
, wanted_net_name
) == 0) {
822 if (o_attrib_string_get_name_value (has_attrib
, &has_attrib_name
,
823 &has_attrib_value
) != 0) {
825 o_attrib_search_object_attribs_by_name (nl_current
->object_ptr
,
828 if ( ((has_attrib_value
== NULL
) && (attrib_value
== NULL
)) ||
829 ((has_attrib_value
!= NULL
) && (attrib_value
!= NULL
) &&
830 (strcmp(attrib_value
, has_attrib_value
) == 0)) ) {
831 g_free (attrib_value
);
833 o_attrib_search_object_attribs_by_name (nl_current
->object_ptr
,
836 list
= scm_cons (scm_from_locale_string (attrib_value
), list
);
838 g_free (attrib_value
);
840 g_free (has_attrib_name
);
841 g_free (has_attrib_value
);
845 pl_current
= pl_current
->next
;
847 nl_current
= nl_current
->next
;
858 * This function is in s_rename.c: SCM g_get_renamed_nets(SCM scm_level)