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
30 #include <libgeda/libgeda.h>
31 #include <libgeda/libgedaguile.h>
33 #include "../include/globals.h"
34 #include "../include/prototype.h"
36 #ifdef HAVE_LIBDMALLOC
41 SCM
g_scm_c_get_uref (TOPLEVEL
*toplevel
, OBJECT
*object
)
43 SCM func
= scm_variable_ref (scm_c_lookup ("get-uref"));
44 SCM object_smob
= edascm_from_object (object
);
45 SCM exp
= scm_list_2 (func
, object_smob
);
47 return g_scm_eval_protected (exp
, SCM_UNDEFINED
);
51 /* this function will only return a unique list of packages */
52 SCM
g_get_packages(SCM level
)
57 NETLIST
*nl_current
= NULL
;
59 SCM_ASSERT(scm_is_string (level
), level
, SCM_ARG1
, "gnetlist:get-pins");
61 /* build a hash table */
62 ht
= g_hash_table_new (g_str_hash
, g_str_equal
);
63 for (nl_current
= netlist_head
; nl_current
!= NULL
;
64 nl_current
= nl_current
->next
) {
65 if (nl_current
->component_uref
!= NULL
) {
66 /* add component_uref in the hash table */
67 /* uniqueness of component_uref is guaranteed by the hashtable */
69 if (g_hash_table_lookup (ht
, nl_current
->component_uref
) == NULL
) {
70 g_hash_table_insert (ht
, nl_current
->component_uref
,
71 nl_current
->component_uref
);
72 list
= scm_cons (scm_from_utf8_string (nl_current
->component_uref
),
77 g_hash_table_destroy (ht
);
82 /* this function will only return a non unique list of packages */
83 SCM
g_get_non_unique_packages(SCM level
)
87 NETLIST
*nl_current
= NULL
;
89 SCM_ASSERT(scm_is_string (level
), level
, SCM_ARG1
, "gnetlist:get-pins");
91 for (nl_current
= netlist_head
; nl_current
!= NULL
;
92 nl_current
= nl_current
->next
) {
93 if (nl_current
->component_uref
!= NULL
) {
94 list
= scm_cons (scm_from_utf8_string (nl_current
->component_uref
),
103 SCM
g_get_pins(SCM scm_uref
)
108 CPINLIST
*pl_current
;
110 SCM_ASSERT(scm_is_string (scm_uref
), scm_uref
, SCM_ARG1
, "gnetlist:get-pins");
112 uref
= scm_to_utf8_string (scm_uref
);
114 /* here is where you make it multi page aware */
115 nl_current
= netlist_head
;
117 /* search for the first instance */
118 /* through the entire list */
119 while (nl_current
!= NULL
) {
121 if (nl_current
->component_uref
) {
122 if (strcmp(nl_current
->component_uref
, uref
) == 0) {
124 pl_current
= nl_current
->cpins
;
125 while (pl_current
!= NULL
) {
126 if (pl_current
->pin_number
) {
127 list
= scm_cons (scm_from_utf8_string (pl_current
->pin_number
),
130 pl_current
= pl_current
->next
;
134 nl_current
= nl_current
->next
;
142 SCM
g_get_all_nets(SCM scm_level
)
147 CPINLIST
*pl_current
;
150 SCM_ASSERT(scm_is_string (scm_level
), scm_level
, SCM_ARG1
,
151 "gnetlist:get-all-nets");
153 nl_current
= netlist_head
;
155 /* walk through the list of components, and through the list
156 * of individual pins on each, adding net names to the list
157 * being careful to ignore duplicates, and unconnected pins
159 while (nl_current
!= NULL
) {
160 pl_current
= nl_current
->cpins
;
161 while (pl_current
!= NULL
) {
162 if (pl_current
->net_name
) {
164 net_name
= pl_current
->net_name
;
165 /* filter off unconnected pins */
166 if (strncmp(net_name
, "unconnected_pin", 15) != 0) {
167 /*printf("Got net: `%s'\n",net_name); */
168 /* add the net name to the list */
170 printf("Got net: `%s'\n", net_name
);
171 printf("pin %s\n", pl_current
->pin_number
);
173 list
= scm_cons (scm_from_utf8_string (net_name
),
177 pl_current
= pl_current
->next
;
179 nl_current
= nl_current
->next
;
185 SCM
g_get_all_unique_nets(SCM scm_level
)
191 CPINLIST
*pl_current
;
194 SCM_ASSERT(scm_is_string (scm_level
), scm_level
, SCM_ARG1
,
195 "gnetlist:get-all-unique-nets");
197 nl_current
= netlist_head
;
199 /* walk through the list of components, and through the list
200 * of individual pins on each, adding net names to the list
201 * being careful to ignore duplicates, and unconnected pins
203 while (nl_current
!= NULL
) {
204 pl_current
= nl_current
->cpins
;
205 while (pl_current
!= NULL
) {
206 if (pl_current
->net_name
) {
208 net_name
= pl_current
->net_name
;
209 /* filter off unconnected pins */
210 if (strncmp(net_name
, "unconnected_pin", 15) != 0) {
211 /* add the net name to the list */
212 /*printf("Got net: `%s'\n",net_name); */
214 x
= scm_from_utf8_string (net_name
);
215 if (scm_is_false (scm_member (x
, list
))) {
216 list
= scm_cons (x
, list
);
220 pl_current
= pl_current
->next
;
222 nl_current
= nl_current
->next
;
228 /* given a net name, return all connections */
229 SCM
g_get_all_connections(SCM scm_netname
)
234 SCM is_member
= SCM_EOL
;
235 SCM connlist
= SCM_EOL
;
236 SCM pairlist
= SCM_EOL
;
238 CPINLIST
*pl_current
;
240 char *wanted_net_name
;
245 SCM_ASSERT(scm_is_string(scm_netname
), scm_netname
, SCM_ARG1
,
246 "gnetlist:get-all-connections");
248 wanted_net_name
= scm_to_utf8_string (scm_netname
);
250 if (wanted_net_name
== NULL
) {
255 nl_current
= netlist_head
;
257 /* walk through the list of components, and through the list
258 * of individual pins on each, adding net names to the list
259 * being careful to ignore duplicates, and unconnected pins
261 while (nl_current
!= NULL
) {
262 pl_current
= nl_current
->cpins
;
263 while (pl_current
!= NULL
) {
264 if (pl_current
->net_name
) {
266 net_name
= pl_current
->net_name
;
267 /* filter off unconnected pins */
268 if (strcmp(net_name
, wanted_net_name
) == 0) {
269 /* add the net name to the list */
272 printf("found net: `%s'\n", net_name
);
275 n_current
= pl_current
->nets
;
276 while (n_current
!= NULL
) {
278 if (n_current
->connected_to
) {
281 pin
= (char *) g_malloc(sizeof(char) *
285 (char *) g_malloc(sizeof(char) *
289 sscanf(n_current
->connected_to
,
292 pairlist
= scm_list_n (scm_from_utf8_string (uref
),
293 scm_from_utf8_string (pin
),
297 is_member
= scm_member(x
, connlist
);
299 if (scm_is_false (is_member
)) {
300 connlist
= scm_cons (pairlist
, connlist
);
306 n_current
= n_current
->next
;
310 pl_current
= pl_current
->next
;
312 nl_current
= nl_current
->next
;
315 free (wanted_net_name
);
319 /* Given a uref and a pin number return a list of: */
320 /* (netname (uref pin) (uref pin) ... ) */
321 SCM
g_get_nets(SCM scm_uref
, SCM scm_pin
)
323 SCM outerlist
= SCM_EOL
;
324 SCM pinslist
= SCM_EOL
;
325 SCM pairlist
= SCM_EOL
;
326 NETLIST
*nl_current
= NULL
;
327 CPINLIST
*pl_current
= NULL
;
329 char *wanted_uref
= NULL
;
330 char *wanted_pin
= NULL
;
331 char *net_name
= NULL
;
336 SCM_ASSERT(scm_is_string (scm_uref
), scm_uref
, SCM_ARG1
,
337 "gnetlist:get-nets");
339 SCM_ASSERT(scm_is_string (scm_pin
), scm_pin
, SCM_ARG2
,
340 "gnetlist:get-nets");
342 scm_dynwind_begin (0);
344 wanted_uref
= scm_to_utf8_string (scm_uref
);
345 scm_dynwind_free (wanted_uref
);
347 wanted_pin
= scm_to_utf8_string (scm_pin
);
348 scm_dynwind_free (wanted_pin
);
350 nl_current
= netlist_head
;
352 /* search for the first instance */
353 /* through the entire list */
354 while (nl_current
!= NULL
) {
356 if (nl_current
->component_uref
) {
358 if (strcmp(nl_current
->component_uref
, wanted_uref
) == 0) {
360 pl_current
= nl_current
->cpins
;
361 while (pl_current
!= NULL
) {
363 if (pl_current
->pin_number
) {
364 if (strcmp(pl_current
->pin_number
, wanted_pin
) ==
367 n_current
= pl_current
->nets
;
369 if (pl_current
->net_name
) {
370 net_name
= pl_current
->net_name
;
373 while (n_current
!= NULL
) {
375 if (n_current
->connected_to
) {
378 pin
= (char *) g_malloc(sizeof(char) *
383 (char *) g_malloc(sizeof(char) *
387 sscanf(n_current
->connected_to
,
390 pairlist
= scm_list_n (scm_from_utf8_string (uref
),
391 scm_from_utf8_string (pin
),
394 pinslist
= scm_cons (pairlist
, pinslist
);
399 n_current
= n_current
->next
;
403 pl_current
= pl_current
->next
;
407 nl_current
= nl_current
->next
;
412 if (net_name
!= NULL
) {
413 outerlist
= scm_cons (scm_from_utf8_string (net_name
), pinslist
);
415 outerlist
= scm_cons (scm_from_utf8_string ("ERROR_INVALID_PIN"),
417 fprintf(stderr
, "Invalid wanted_pin passed to get-nets [%s]\n",
425 /* Given a uref, Return a list of pairs, each pair contains the name
426 * of the pin, and the name of the net connected to that pin.
428 SCM
g_get_pins_nets(SCM scm_uref
)
430 SCM pinslist
= SCM_EOL
;
431 SCM pairlist
= SCM_EOL
;
432 NETLIST
*nl_current
= NULL
;
433 CPINLIST
*pl_current
= NULL
;
435 char *wanted_uref
= NULL
;
436 char *net_name
= NULL
;
439 SCM_ASSERT(scm_is_string (scm_uref
),
440 scm_uref
, SCM_ARG1
, "gnetlist:get-pins-nets");
442 wanted_uref
= scm_to_utf8_string (scm_uref
);
444 /* search for the any instances */
445 /* through the entire list */
446 for (nl_current
= netlist_head
; nl_current
!= NULL
;
447 nl_current
= nl_current
->next
) {
449 /* is there a uref? */
450 if (nl_current
->component_uref
) {
451 /* is it the one we want ? */
452 if (strcmp(nl_current
->component_uref
, wanted_uref
) == 0) {
454 for (pl_current
= nl_current
->cpins
; pl_current
!= NULL
;
455 pl_current
= pl_current
->next
) {
456 /* is there a valid pin number and a valid name ? */
457 if (pl_current
->pin_number
) {
458 if (pl_current
->net_name
) {
459 /* yes, add it to the list */
460 pin
= pl_current
->pin_number
;
461 net_name
= pl_current
->net_name
;
463 pairlist
= scm_cons (scm_from_utf8_string (pin
),
464 scm_from_utf8_string (net_name
));
465 pinslist
= scm_cons (pairlist
, pinslist
);
476 pinslist
= scm_reverse (pinslist
); /* pins are in reverse order on the way
483 /*! \brief Get attribute value(s) from a package with given uref.
484 * \par Function Description
485 * This function returns the values of a specific attribute type
486 * attached to the symbol instances with the given refdes.
488 * Every first attribute value found is added to the return list. A
489 * Scheme false value is added if the instance has no such attribute.
491 * \note The order of the values in the return list is the order of
492 * symbol instances within gnetlist (the first element is the value
493 * associated with the first symbol instance).
495 * \param [in] scm_uref Package reference.
496 * \param [in] scm_wanted_attrib Attribute name.
497 * \return A list of attribute values as strings and #f.
499 SCM
g_get_all_package_attributes(SCM scm_uref
, SCM scm_wanted_attrib
)
506 SCM_ASSERT(scm_is_string (scm_uref
),
507 scm_uref
, SCM_ARG1
, "gnetlist:get-all-package-attributes");
509 SCM_ASSERT(scm_is_string (scm_wanted_attrib
),
510 scm_wanted_attrib
, SCM_ARG2
, "gnetlist:get-all-package-attributes");
512 uref
= scm_to_utf8_string (scm_uref
);
513 wanted_attrib
= scm_to_utf8_string (scm_wanted_attrib
);
515 /* here is where you make it multi page aware */
516 nl_current
= netlist_head
;
518 /* search for uref instances and through the entire list */
519 while (nl_current
!= NULL
) {
521 if (nl_current
->component_uref
) {
522 if (strcmp(nl_current
->component_uref
, uref
) == 0) {
524 o_attrib_search_object_attribs_by_name (nl_current
->object_ptr
,
527 ret
= scm_cons (value
? scm_from_utf8_string (value
) : SCM_BOOL_F
, ret
);
532 nl_current
= nl_current
->next
;
536 free (wanted_attrib
);
538 return scm_reverse_x (ret
, SCM_EOL
);
541 /* takes a uref and pinseq number and returns wanted_attribute associated */
542 /* with that pinseq pin and component */
543 SCM
g_get_attribute_by_pinseq(SCM scm_uref
, SCM scm_pinseq
,
544 SCM scm_wanted_attrib
)
546 SCM scm_return_value
;
551 char *return_value
= NULL
;
552 OBJECT
*o_pin_object
;
554 SCM_ASSERT(scm_is_string (scm_uref
),
555 scm_uref
, SCM_ARG1
, "gnetlist:get-pin-number-seq");
557 SCM_ASSERT(scm_is_string (scm_pinseq
),
558 scm_pinseq
, SCM_ARG2
, "gnetlist:get-pin-number-seq");
561 SCM_ASSERT(scm_is_string (scm_wanted_attrib
),
562 scm_wanted_attrib
, SCM_ARG3
, "gnetlist:get-pin-attribute-seq");
564 scm_dynwind_begin (0);
566 uref
= scm_to_utf8_string (scm_uref
);
567 scm_dynwind_free (uref
);
569 pinseq
= scm_to_utf8_string (scm_pinseq
);
570 scm_dynwind_free (pinseq
);
572 wanted_attrib
= scm_to_utf8_string (scm_wanted_attrib
);
573 scm_dynwind_free (wanted_attrib
);
576 printf("gnetlist:g_netlist.c:g_get_attribute_by_pinseq -- \n");
577 printf(" wanted uref = %s\n", uref
);
578 printf(" wanted_pin_seq = %s\n", pinseq
);
579 printf(" wanted_attrib = %s\n", wanted_attrib
);
582 /* here is where you make it multi page aware */
583 nl_current
= netlist_head
;
585 /* search for the first instance */
586 /* through the entire list */
587 while (nl_current
!= NULL
) {
589 if (nl_current
->component_uref
) {
590 if (strcmp(nl_current
->component_uref
, uref
) == 0) {
592 o_pin_object
= o_complex_find_pin_by_attribute (nl_current
->object_ptr
,
597 o_attrib_search_object_attribs_by_name (o_pin_object
,
604 /* Don't break until we search the whole netlist to handle slotted */
605 /* parts. 4.28.2007 -- SDB. */
608 nl_current
= nl_current
->next
;
614 scm_return_value
= scm_from_utf8_string (return_value
);
616 scm_return_value
= scm_from_utf8_string ("unknown");
620 printf("gnetlist:g_netlist.c:g_get_attribute_by_pinseq -- ");
621 printf("return_value: %s\n", return_value
);
624 return (scm_return_value
);
627 /* this takes a pin number and returns the appropriate attribute on that pin*/
628 /* scm_pin is the value associated with the pinnumber= attribute and uref */
629 SCM
g_get_attribute_by_pinnumber(SCM scm_uref
, SCM scm_pin
, SCM
632 SCM scm_return_value
;
638 char *return_value
= NULL
;
641 SCM_ASSERT(scm_is_string (scm_uref
),
642 scm_uref
, SCM_ARG1
, "gnetlist:get-pin-attribute");
644 SCM_ASSERT(scm_is_string (scm_pin
),
645 scm_pin
, SCM_ARG2
, "gnetlist:get-pin-attribute");
647 SCM_ASSERT(scm_is_string (scm_wanted_attrib
),
648 scm_wanted_attrib
, SCM_ARG3
, "gnetlist:get-pin-attribute");
650 scm_dynwind_begin (0);
652 uref
= scm_to_utf8_string (scm_uref
);
653 scm_dynwind_free (uref
);
655 pin
= scm_to_utf8_string (scm_pin
);
656 scm_dynwind_free (pin
);
658 wanted_attrib
= scm_to_utf8_string (scm_wanted_attrib
);
659 scm_dynwind_free (wanted_attrib
);
661 /* here is where you make it multi page aware */
662 nl_current
= netlist_head
;
664 /* search for the first instance */
665 /* through the entire list */
666 while (nl_current
!= NULL
&& !done
) {
667 if (nl_current
->component_uref
) {
668 if (strcmp(nl_current
->component_uref
, uref
) == 0) {
671 o_complex_find_pin_by_attribute (nl_current
->object_ptr
,
676 /* only look for the first occurance of wanted_attrib */
678 o_attrib_search_object_attribs_by_name (pin_object
,
682 printf("GOT IT: %s\n", return_value
);
685 } else if (strcmp("pintype",
686 wanted_attrib
) == 0) {
687 if (nl_current
->cpins
) {
688 CPINLIST
*pinobject
=
689 s_cpinlist_search_pin(nl_current
->cpins
, pin
);
694 printf("Supplied pintype 'pwr' for artificial pin '%s' of '%s'\n",
702 nl_current
= nl_current
->next
;
708 scm_return_value
= scm_from_utf8_string (return_value
);
710 scm_return_value
= scm_from_utf8_string ("unknown");
713 return (scm_return_value
);
717 /* returns value of attribute otherwise string "none" */
718 /* still highly temp and doesn't work right */
719 SCM
g_get_toplevel_attribute(SCM scm_wanted_attrib
)
724 char *attrib_value
= NULL
;
725 SCM scm_return_value
;
726 TOPLEVEL
*toplevel
= edascm_c_current_toplevel ();
728 SCM_ASSERT(scm_is_string (scm_wanted_attrib
),
729 scm_wanted_attrib
, SCM_ARG1
, "gnetlist:get-toplevel-attribute");
731 wanted_attrib
= scm_to_utf8_string (scm_wanted_attrib
);
733 for (p_iter
= geda_list_get_glist (toplevel
->pages
); p_iter
!= NULL
;
734 p_iter
= g_list_next (p_iter
)) {
735 p_current
= p_iter
->data
;
737 /* only look for first occurrance of the attribute on each page */
739 o_attrib_search_floating_attribs_by_name (s_page_objects (p_current
),
742 /* Stop when we find the first one */
743 if (attrib_value
!= NULL
)
747 free (wanted_attrib
);
749 if (attrib_value
!= NULL
) {
750 scm_return_value
= scm_from_utf8_string (attrib_value
);
751 g_free (attrib_value
);
753 scm_return_value
= scm_from_utf8_string ("not found");
756 return (scm_return_value
);
760 /*! \brief Obtain a list of `-O' backend arguments.
761 * \par Function Description
762 * Returns a list of arguments passed to the gnetlist backend via the
763 * `-O' gnetlist command-line option.
766 g_get_backend_arguments()
768 SCM result
= SCM_EOL
;
771 for (iter
= backend_params
; iter
!= NULL
; iter
= g_slist_next (iter
)) {
772 result
= scm_cons (scm_from_locale_string ((char *) iter
->data
),
776 return scm_reverse_x (result
, SCM_UNDEFINED
);
780 /*! \brief Get input files from command line.
781 * \par Function Description
782 * This function returns a list of the files named on the command line.
784 * \return A list of filenames as strings.
786 SCM
g_get_input_files()
789 GSList
*current
= input_files
;
791 while (current
!= NULL
) {
792 list
= scm_cons (scm_from_locale_string (current
->data
), list
);
793 current
= g_slist_next(current
);
796 return scm_reverse_x (list
, SCM_EOL
);
800 /* given a net name, an attribute, and a wanted attribute, return all
801 the given attribute of all the graphical objects connected to that
803 SCM
g_graphical_objs_in_net_with_attrib_get_attrib (SCM scm_netname
, SCM scm_has_attribute
, SCM scm_wanted_attribute
)
808 CPINLIST
*pl_current
;
809 char *wanted_net_name
;
813 char *attrib_value
=NULL
;
814 char *has_attrib_value
= NULL
;
815 char *has_attrib_name
= NULL
;
817 SCM_ASSERT(scm_is_string (scm_netname
), scm_netname
, SCM_ARG1
,
818 "gnetlist:get-attr-of-conn-graph-objs-with-attr");
820 SCM_ASSERT(scm_is_string (scm_wanted_attribute
),
821 scm_wanted_attribute
, SCM_ARG3
,
822 "gnetlist:get-attr-of-conn-graph-objs-with-attr");
824 SCM_ASSERT(scm_is_string (scm_has_attribute
),
825 scm_has_attribute
, SCM_ARG2
,
826 "gnetlist:get-attr-of-conn-graph-objs-with-attr");
828 scm_dynwind_begin (0);
830 wanted_net_name
= scm_to_utf8_string (scm_netname
);
831 if (wanted_net_name
== NULL
) {
835 scm_dynwind_free (wanted_net_name
);
837 wanted_attrib
= scm_to_utf8_string (scm_wanted_attribute
);
838 scm_dynwind_free (wanted_attrib
);
840 has_attrib
= scm_to_utf8_string (scm_has_attribute
);
841 scm_dynwind_free (has_attrib
);
843 nl_current
= graphical_netlist_head
;
845 /* walk through the list of components, and through the list
846 * of individual pins on each, adding net names to the list
847 * being careful to ignore duplicates, and unconnected pins
849 while (nl_current
!= NULL
) {
850 pl_current
= nl_current
->cpins
;
851 while (pl_current
!= NULL
) {
852 if (pl_current
->net_name
) {
853 net_name
= pl_current
->net_name
;
854 if (strcmp(net_name
, wanted_net_name
) == 0) {
856 if (o_attrib_string_get_name_value (has_attrib
, &has_attrib_name
,
857 &has_attrib_value
) != 0) {
859 o_attrib_search_object_attribs_by_name (nl_current
->object_ptr
,
862 if ( ((has_attrib_value
== NULL
) && (attrib_value
== NULL
)) ||
863 ((has_attrib_value
!= NULL
) && (attrib_value
!= NULL
) &&
864 (strcmp(attrib_value
, has_attrib_value
) == 0)) ) {
865 g_free (attrib_value
);
867 o_attrib_search_object_attribs_by_name (nl_current
->object_ptr
,
870 list
= scm_cons (scm_from_utf8_string (attrib_value
), list
);
872 g_free (attrib_value
);
874 g_free (has_attrib_name
);
875 g_free (has_attrib_value
);
879 pl_current
= pl_current
->next
;
881 nl_current
= nl_current
->next
;
893 * This function is in s_rename.c: SCM g_get_renamed_nets(SCM scm_level)