4 * \brief Generic netlist operations.
8 * <h1><b>Copyright.</b></h1>\n
10 * PCB, interactive printed circuit board design
12 * Copyright (C) 1994,1995,1996, 2005 Thomas Nau
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 * Contact addresses for paper mail and Email:
30 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
32 * Thomas.Nau@rz.uni-ulm.de
44 #include <sys/types.h>
68 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
72 #ifdef HAVE_LIBDMALLOC
77 int PCB->NetlistLib.MenuN
78 char * PCB->NetlistLib.Menu[i].Name
79 [0] == '*' (ok for rats) or ' ' (skip for rats)
82 char * PCB->NetlistLib.Menu[i].Style
83 int PCB->NetlistLib.Menu[i].EntryN
84 char * PCB->NetlistLib.Menu[i].Entry[j].ListEntry
87 typedef void (*NFunc
) (LibraryMenuType
*, LibraryEntryType
*);
89 int netlist_frozen
= 0;
90 static int netlist_needs_update
= 0;
93 NetlistChanged (int force_unfreeze
)
98 netlist_needs_update
= 1;
101 netlist_needs_update
= 0;
102 hid_action ("NetlistChanged");
107 netnode_to_netname (char *nodename
)
110 /*printf("nodename [%s]\n", nodename);*/
111 for (i
=0; i
<PCB
->NetlistLib
.MenuN
; i
++)
113 for (j
=0; j
<PCB
->NetlistLib
.Menu
[i
].EntryN
; j
++)
115 if (strcmp (PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
, nodename
) == 0)
117 /*printf(" in [%s]\n", PCB->NetlistLib.Menu[i].Name);*/
118 return & (PCB
->NetlistLib
.Menu
[i
]);
126 netname_to_netname (char *netname
)
130 if ((netname
[0] == '*' || netname
[0] == ' ') && netname
[1] == ' ')
132 /* Looks like we were passed an internal netname, skip the prefix */
135 for (i
=0; i
<PCB
->NetlistLib
.MenuN
; i
++)
137 if (strcmp (PCB
->NetlistLib
.Menu
[i
].Name
+ 2, netname
) == 0)
139 return & (PCB
->NetlistLib
.Menu
[i
]);
146 pin_name_to_xy (LibraryEntryType
* pin
, int *x
, int *y
)
149 if (!SeekPad (pin
, &conn
, false))
154 *x
= ((PinType
*) (conn
.ptr2
))->X
;
155 *y
= ((PinType
*) (conn
.ptr2
))->Y
;
158 *x
= ((PadType
*) (conn
.ptr2
))->Point1
.X
;
159 *y
= ((PadType
*) (conn
.ptr2
))->Point1
.Y
;
166 netlist_find (LibraryMenuType
* net
, LibraryEntryType
* pin
)
169 if (pin_name_to_xy (net
->Entry
, &x
, &y
))
171 LookupConnection (x
, y
, 1, 1, FOUNDFLAG
, true, true);
175 netlist_select (LibraryMenuType
* net
, LibraryEntryType
* pin
)
178 if (pin_name_to_xy (net
->Entry
, &x
, &y
))
180 LookupConnection (x
, y
, 1, 1, SELECTEDFLAG
, true, true);
184 netlist_rats (LibraryMenuType
* net
, LibraryEntryType
* pin
)
192 netlist_norats (LibraryMenuType
* net
, LibraryEntryType
* pin
)
200 * \brief The primary purpose of this action is to remove the netlist
201 * completely so that a new one can be loaded, usually via a gsch2pcb
205 netlist_clear (LibraryMenuType
* net
, LibraryEntryType
* pin
)
207 LibraryType
*netlist
= &PCB
->NetlistLib
;
212 /* Clear the entire netlist. */
213 FreeLibraryMemory (&PCB
->NetlistLib
);
217 /* Remove a net from the netlist. */
218 ni
= net
- netlist
->Menu
;
219 if (ni
>= 0 && ni
< netlist
->MenuN
)
221 /* if there is exactly one item, MenuN is 1 and ni is 0 */
222 if (netlist
->MenuN
- ni
> 1)
223 memmove (net
, net
+1, (netlist
->MenuN
- ni
- 1) * sizeof (*net
));
229 /* Remove a pin from the given net. Note that this may leave an
230 empty net, which is different than removing the net
232 pi
= pin
- net
->Entry
;
233 if (pi
>= 0 && pi
< net
->EntryN
)
235 /* if there is exactly one item, MenuN is 1 and ni is 0 */
236 if (net
->EntryN
- pi
> 1)
237 memmove (pin
, pin
+1, (net
->EntryN
- pi
- 1) * sizeof (*pin
));
245 netlist_style (LibraryMenuType
*net
, const char *style
)
248 net
->Style
= STRDUP ((char *)style
);
252 netlist_netclass (LibraryMenuType
*net
, const char *netclass
)
254 free (net
->Netclass
);
255 net
->Netclass
= STRDUP ((char *)netclass
);
259 * \brief The primary purpose of this action is to rebuild a netlist
260 * from a script, in conjunction with the clear action above.
263 netlist_add (const char *netname
, const char *pinname
)
266 LibraryType
*netlist
= &PCB
->NetlistLib
;
267 LibraryMenuType
*net
= NULL
;
268 LibraryEntryType
*pin
= NULL
;
270 for (ni
=0; ni
<netlist
->MenuN
; ni
++)
271 if (strcmp (netlist
->Menu
[ni
].Name
+2, netname
) == 0)
273 net
= & (netlist
->Menu
[ni
]);
278 net
= CreateNewNet (netlist
, (char *)netname
, NULL
, NULL
);
281 for (pi
=0; pi
<net
->EntryN
; pi
++)
282 if (strcmp (net
->Entry
[pi
].ListEntry
, pinname
) == 0)
284 pin
= & (net
->Entry
[pi
]);
289 pin
= CreateNewConnection (net
, (char *)pinname
);
296 static const char netlist_syntax
[] =
297 "Net(find|select|rats|norats|clear[,net[,pin]])\n"
298 "Net(freeze|thaw|forcethaw)\n"
301 static const char netlist_help
[] = "Perform various actions on netlists.";
303 /* %start-doc actions Netlist
305 Each of these actions apply to a specified set of nets. @var{net} and
306 @var{pin} are patterns which match one or more nets or pins; these
307 patterns may be full names or regular expressions. If an exact match
308 is found, it is the only match; if no exact match is found,
309 @emph{then} the pattern is tried as a regular expression.
311 If neither @var{net} nor @var{pin} are specified, all nets apply. If
312 @var{net} is specified but not @var{pin}, all nets matching @var{net}
313 apply. If both are specified, nets which match @var{net} and contain
314 a pin matching @var{pin} apply.
319 Nets which apply are marked @emph{found} and are drawn in the
320 @code{connected-color} color.
323 Nets which apply are selected.
326 Nets which apply are marked as available for the rats nest.
329 Nets which apply are marked as not available for the rats nest.
335 Add the given pin to the given netlist, creating either if needed.
338 Called after a list of add's, this sorts the netlist.
343 Temporarily prevents changes to the netlist from being reflected in
344 the GUI. For example, if you need to make multiple changes, you
345 freeze the netlist, make the changes, then thaw it. Note that
346 freeze/thaw requests may nest, with the netlist being fully thawed
347 only when all pending freezes are thawed. You can bypass the nesting
348 by using forcethaw, which resets the freeze count and immediately
355 #define ARG(n) (argc > (n) ? argv[n] : 0)
358 Netlist (int argc
, char **argv
, Coord x
, Coord y
)
362 LibraryMenuType
*net
;
363 LibraryEntryType
*pin
;
369 #if defined(HAVE_REGCOMP)
373 #if defined(HAVE_RE_COMP)
381 Message (netlist_syntax
);
384 if (strcasecmp (argv
[0], "find") == 0)
386 else if (strcasecmp (argv
[0], "select") == 0)
387 func
= netlist_select
;
388 else if (strcasecmp (argv
[0], "rats") == 0)
390 else if (strcasecmp (argv
[0], "norats") == 0)
391 func
= netlist_norats
;
392 else if (strcasecmp (argv
[0], "clear") == 0)
394 func
= netlist_clear
;
397 netlist_clear (NULL
, NULL
);
401 else if (strcasecmp (argv
[0], "style") == 0)
402 func
= (NFunc
)netlist_style
;
403 else if (strcasecmp (argv
[0], "class") == 0)
404 func
= (NFunc
)netlist_netclass
;
405 else if (strcasecmp (argv
[0], "add") == 0)
407 /* Add is different, because the net/pin won't already exist. */
408 return netlist_add (ARG(1), ARG(2)); /* Net class? */
410 else if (strcasecmp (argv
[0], "sort") == 0)
415 else if (strcasecmp (argv
[0], "freeze") == 0)
420 else if (strcasecmp (argv
[0], "thaw") == 0)
422 if (netlist_frozen
> 0)
425 if (netlist_needs_update
)
430 else if (strcasecmp (argv
[0], "forcethaw") == 0)
433 if (netlist_needs_update
)
439 Message (netlist_syntax
);
448 for (i
= 0; i
< PCB
->NetlistLib
.MenuN
; i
++)
450 net
= PCB
->NetlistLib
.Menu
+ i
;
451 if (strcasecmp (argv
[1], net
->Name
+ 2) == 0)
456 #if defined(HAVE_REGCOMP)
458 regcomp (&elt_pattern
, argv
[1],
459 REG_EXTENDED
| REG_ICASE
| REG_NOSUB
);
462 char errorstring
[128];
464 regerror (result
, &elt_pattern
, errorstring
, 128);
465 Message (_("regexp error: %s\n"), errorstring
);
466 regfree (&elt_pattern
);
470 #if defined(HAVE_RE_COMP)
471 if ((elt_pattern
= re_comp (argv
[1])) != NULL
)
473 Message (_("re_comp error: %s\n"), elt_pattern
);
481 for (i
= PCB
->NetlistLib
.MenuN
-1; i
>= 0; i
--)
483 net
= PCB
->NetlistLib
.Menu
+ i
;
490 #if defined(HAVE_REGCOMP)
491 if (regexec (&elt_pattern
, net
->Name
+ 2, 1, &match
, 0) != 0)
494 #if defined(HAVE_RE_COMP)
495 if (re_exec (net
->Name
+ 2) != 1)
501 if (strcasecmp (net
->Name
+ 2, argv
[1]))
507 if (func
== (void *)netlist_style
)
509 netlist_style (net
, ARG(2));
511 else if (func
== (void *)netlist_netclass
)
513 netlist_netclass (net
, ARG(2));
517 int l
= strlen (argv
[2]);
518 for (j
= net
->EntryN
-1; j
>= 0 ; j
--)
519 if (strcasecmp (net
->Entry
[j
].ListEntry
, argv
[2]) == 0
520 || (strncasecmp (net
->Entry
[j
].ListEntry
, argv
[2], l
) == 0
521 && net
->Entry
[j
].ListEntry
[l
] == '-'))
523 pin
= net
->Entry
+ j
;
532 if (argc
> 2 && !pin_found
)
534 gui
->log ("Net %s has no pin %s\n", argv
[1], argv
[2]);
539 gui
->log ("No net named %s\n", argv
[1]);
543 regfree (&elt_pattern
);
549 HID_Action netlist_action_list
[] = {
551 netlist_help
, netlist_syntax
}
553 {"netlist", 0, Netlist
,
554 netlist_help
, netlist_syntax
}
557 REGISTER_ACTIONS (netlist_action_list
)