pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00035 #ifdef HAVE_CONFIG_H 00036 #include "config.h" 00037 #endif 00038 00039 #include <stdlib.h> 00040 #ifdef HAVE_STRING_H 00041 #include <string.h> 00042 #endif 00043 #include <ctype.h> 00044 #include <sys/types.h> 00045 #ifdef HAVE_REGEX_H 00046 #include <regex.h> 00047 #endif 00048 00049 #include "global.h" 00050 #include "action.h" 00051 #include "buffer.h" 00052 #include "data.h" 00053 #include "djopt.h" 00054 #include "error.h" 00055 #include "file.h" 00056 #include "find.h" 00057 #include "mymem.h" 00058 #include "misc.h" 00059 #include "rats.h" 00060 #include "set.h" 00061 #include "vendor.h" 00062 #include "create.h" 00063 00064 #ifdef HAVE_REGCOMP 00065 #undef HAVE_RE_COMP 00066 #endif 00067 00068 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP) 00069 #define USE_RE 00070 #endif 00071 00072 #ifdef HAVE_LIBDMALLOC 00073 #include <dmalloc.h> 00074 #endif 00075 00076 /* 00077 int PCB->NetlistLib.MenuN 00078 char * PCB->NetlistLib.Menu[i].Name 00079 [0] == '*' (ok for rats) or ' ' (skip for rats) 00080 [1] == unused 00081 [2..] actual name 00082 char * PCB->NetlistLib.Menu[i].Style 00083 int PCB->NetlistLib.Menu[i].EntryN 00084 char * PCB->NetlistLib.Menu[i].Entry[j].ListEntry 00085 */ 00086 00087 typedef void (*NFunc) (LibraryMenuType *, LibraryEntryType *); 00088 00089 int netlist_frozen = 0; 00090 static int netlist_needs_update = 0; 00091 00092 void 00093 NetlistChanged (int force_unfreeze) 00094 { 00095 if (force_unfreeze) 00096 netlist_frozen = 0; 00097 if (netlist_frozen) 00098 netlist_needs_update = 1; 00099 else 00100 { 00101 netlist_needs_update = 0; 00102 hid_action ("NetlistChanged"); 00103 } 00104 } 00105 00106 LibraryMenuType * 00107 netnode_to_netname (char *nodename) 00108 { 00109 int i, j; 00110 /*printf("nodename [%s]\n", nodename);*/ 00111 for (i=0; i<PCB->NetlistLib.MenuN; i++) 00112 { 00113 for (j=0; j<PCB->NetlistLib.Menu[i].EntryN; j++) 00114 { 00115 if (strcmp (PCB->NetlistLib.Menu[i].Entry[j].ListEntry, nodename) == 0) 00116 { 00117 /*printf(" in [%s]\n", PCB->NetlistLib.Menu[i].Name);*/ 00118 return & (PCB->NetlistLib.Menu[i]); 00119 } 00120 } 00121 } 00122 return 0; 00123 } 00124 00125 LibraryMenuType * 00126 netname_to_netname (char *netname) 00127 { 00128 int i; 00129 00130 if ((netname[0] == '*' || netname[0] == ' ') && netname[1] == ' ') 00131 { 00132 /* Looks like we were passed an internal netname, skip the prefix */ 00133 netname += 2; 00134 } 00135 for (i=0; i<PCB->NetlistLib.MenuN; i++) 00136 { 00137 if (strcmp (PCB->NetlistLib.Menu[i].Name + 2, netname) == 0) 00138 { 00139 return & (PCB->NetlistLib.Menu[i]); 00140 } 00141 } 00142 return 0; 00143 } 00144 00145 static int 00146 pin_name_to_xy (LibraryEntryType * pin, int *x, int *y) 00147 { 00148 ConnectionType conn; 00149 if (!SeekPad (pin, &conn, false)) 00150 return 1; 00151 switch (conn.type) 00152 { 00153 case PIN_TYPE: 00154 *x = ((PinType *) (conn.ptr2))->X; 00155 *y = ((PinType *) (conn.ptr2))->Y; 00156 return 0; 00157 case PAD_TYPE: 00158 *x = ((PadType *) (conn.ptr2))->Point1.X; 00159 *y = ((PadType *) (conn.ptr2))->Point1.Y; 00160 return 0; 00161 } 00162 return 1; 00163 } 00164 00165 static void 00166 netlist_find (LibraryMenuType * net, LibraryEntryType * pin) 00167 { 00168 int x, y; 00169 if (pin_name_to_xy (net->Entry, &x, &y)) 00170 return; 00171 LookupConnection (x, y, 1, 1, FOUNDFLAG, true); 00172 } 00173 00174 static void 00175 netlist_select (LibraryMenuType * net, LibraryEntryType * pin) 00176 { 00177 int x, y; 00178 if (pin_name_to_xy (net->Entry, &x, &y)) 00179 return; 00180 LookupConnection (x, y, 1, 1, SELECTEDFLAG, true); 00181 } 00182 00183 static void 00184 netlist_rats (LibraryMenuType * net, LibraryEntryType * pin) 00185 { 00186 net->Name[0] = ' '; 00187 net->flag = 1; 00188 NetlistChanged (0); 00189 } 00190 00191 static void 00192 netlist_norats (LibraryMenuType * net, LibraryEntryType * pin) 00193 { 00194 net->Name[0] = '*'; 00195 net->flag = 0; 00196 NetlistChanged (0); 00197 } 00198 00204 static void 00205 netlist_clear (LibraryMenuType * net, LibraryEntryType * pin) 00206 { 00207 LibraryType *netlist = &PCB->NetlistLib; 00208 int ni, pi; 00209 00210 if (net == 0) 00211 { 00212 /* Clear the entire netlist. */ 00213 FreeLibraryMemory (&PCB->NetlistLib); 00214 } 00215 else if (pin == 0) 00216 { 00217 /* Remove a net from the netlist. */ 00218 ni = net - netlist->Menu; 00219 if (ni >= 0 && ni < netlist->MenuN) 00220 { 00221 /* if there is exactly one item, MenuN is 1 and ni is 0 */ 00222 if (netlist->MenuN - ni > 1) 00223 memmove (net, net+1, (netlist->MenuN - ni - 1) * sizeof (*net)); 00224 netlist->MenuN --; 00225 } 00226 } 00227 else 00228 { 00229 /* Remove a pin from the given net. Note that this may leave an 00230 empty net, which is different than removing the net 00231 (above). */ 00232 pi = pin - net->Entry; 00233 if (pi >= 0 && pi < net->EntryN) 00234 { 00235 /* if there is exactly one item, MenuN is 1 and ni is 0 */ 00236 if (net->EntryN - pi > 1) 00237 memmove (pin, pin+1, (net->EntryN - pi - 1) * sizeof (*pin)); 00238 net->EntryN --; 00239 } 00240 } 00241 NetlistChanged (0); 00242 } 00243 00244 static void 00245 netlist_style (LibraryMenuType *net, const char *style) 00246 { 00247 free (net->Style); 00248 net->Style = STRDUP ((char *)style); 00249 } 00250 00255 static int 00256 netlist_add (const char *netname, const char *pinname) 00257 { 00258 int ni, pi; 00259 LibraryType *netlist = &PCB->NetlistLib; 00260 LibraryMenuType *net = NULL; 00261 LibraryEntryType *pin = NULL; 00262 00263 for (ni=0; ni<netlist->MenuN; ni++) 00264 if (strcmp (netlist->Menu[ni].Name+2, netname) == 0) 00265 { 00266 net = & (netlist->Menu[ni]); 00267 break; 00268 } 00269 if (net == NULL) 00270 { 00271 net = CreateNewNet (netlist, (char *)netname, NULL); 00272 } 00273 00274 for (pi=0; pi<net->EntryN; pi++) 00275 if (strcmp (net->Entry[pi].ListEntry, pinname) == 0) 00276 { 00277 pin = & (net->Entry[pi]); 00278 break; 00279 } 00280 if (pin == NULL) 00281 { 00282 pin = CreateNewConnection (net, (char *)pinname); 00283 } 00284 00285 NetlistChanged (0); 00286 return 0; 00287 } 00288 00289 static const char netlist_syntax[] = 00290 "Net(find|select|rats|norats|clear[,net[,pin]])\n" 00291 "Net(freeze|thaw|forcethaw)\n" 00292 "Net(add,net,pin)"; 00293 00294 static const char netlist_help[] = "Perform various actions on netlists."; 00295 00296 /* %start-doc actions Netlist 00297 00298 Each of these actions apply to a specified set of nets. @var{net} and 00299 @var{pin} are patterns which match one or more nets or pins; these 00300 patterns may be full names or regular expressions. If an exact match 00301 is found, it is the only match; if no exact match is found, 00302 @emph{then} the pattern is tried as a regular expression. 00303 00304 If neither @var{net} nor @var{pin} are specified, all nets apply. If 00305 @var{net} is specified but not @var{pin}, all nets matching @var{net} 00306 apply. If both are specified, nets which match @var{net} and contain 00307 a pin matching @var{pin} apply. 00308 00309 @table @code 00310 00311 @item find 00312 Nets which apply are marked @emph{found} and are drawn in the 00313 @code{connected-color} color. 00314 00315 @item select 00316 Nets which apply are selected. 00317 00318 @item rats 00319 Nets which apply are marked as available for the rats nest. 00320 00321 @item norats 00322 Nets which apply are marked as not available for the rats nest. 00323 00324 @item clear 00325 Clears the netlist. 00326 00327 @item add 00328 Add the given pin to the given netlist, creating either if needed. 00329 00330 @item sort 00331 Called after a list of add's, this sorts the netlist. 00332 00333 @item freeze 00334 @itemx thaw 00335 @itemx forcethaw 00336 Temporarily prevents changes to the netlist from being reflected in 00337 the GUI. For example, if you need to make multiple changes, you 00338 freeze the netlist, make the changes, then thaw it. Note that 00339 freeze/thaw requests may nest, with the netlist being fully thawed 00340 only when all pending freezes are thawed. You can bypass the nesting 00341 by using forcethaw, which resets the freeze count and immediately 00342 updates the GUI. 00343 00344 @end table 00345 00346 %end-doc */ 00347 00348 #define ARG(n) (argc > (n) ? argv[n] : 0) 00349 00350 static int 00351 Netlist (int argc, char **argv, Coord x, Coord y) 00352 { 00353 NFunc func; 00354 int i, j; 00355 LibraryMenuType *net; 00356 LibraryEntryType *pin; 00357 int net_found = 0; 00358 int pin_found = 0; 00359 #if defined(USE_RE) 00360 int use_re = 0; 00361 #endif 00362 #if defined(HAVE_REGCOMP) 00363 regex_t elt_pattern; 00364 regmatch_t match; 00365 #endif 00366 #if defined(HAVE_RE_COMP) 00367 char *elt_pattern; 00368 #endif 00369 00370 if (!PCB) 00371 return 1; 00372 if (argc == 0) 00373 { 00374 Message (netlist_syntax); 00375 return 1; 00376 } 00377 if (strcasecmp (argv[0], "find") == 0) 00378 func = netlist_find; 00379 else if (strcasecmp (argv[0], "select") == 0) 00380 func = netlist_select; 00381 else if (strcasecmp (argv[0], "rats") == 0) 00382 func = netlist_rats; 00383 else if (strcasecmp (argv[0], "norats") == 0) 00384 func = netlist_norats; 00385 else if (strcasecmp (argv[0], "clear") == 0) 00386 { 00387 func = netlist_clear; 00388 if (argc == 1) 00389 { 00390 netlist_clear (NULL, NULL); 00391 return 0; 00392 } 00393 } 00394 else if (strcasecmp (argv[0], "style") == 0) 00395 func = (NFunc)netlist_style; 00396 else if (strcasecmp (argv[0], "add") == 0) 00397 { 00398 /* Add is different, because the net/pin won't already exist. */ 00399 return netlist_add (ARG(1), ARG(2)); 00400 } 00401 else if (strcasecmp (argv[0], "sort") == 0) 00402 { 00403 sort_netlist (); 00404 return 0; 00405 } 00406 else if (strcasecmp (argv[0], "freeze") == 0) 00407 { 00408 netlist_frozen ++; 00409 return 0; 00410 } 00411 else if (strcasecmp (argv[0], "thaw") == 0) 00412 { 00413 if (netlist_frozen > 0) 00414 { 00415 netlist_frozen --; 00416 if (netlist_needs_update) 00417 NetlistChanged (0); 00418 } 00419 return 0; 00420 } 00421 else if (strcasecmp (argv[0], "forcethaw") == 0) 00422 { 00423 netlist_frozen = 0; 00424 if (netlist_needs_update) 00425 NetlistChanged (0); 00426 return 0; 00427 } 00428 else 00429 { 00430 Message (netlist_syntax); 00431 return 1; 00432 } 00433 00434 #if defined(USE_RE) 00435 if (argc > 1) 00436 { 00437 int result; 00438 use_re = 1; 00439 for (i = 0; i < PCB->NetlistLib.MenuN; i++) 00440 { 00441 net = PCB->NetlistLib.Menu + i; 00442 if (strcasecmp (argv[1], net->Name + 2) == 0) 00443 use_re = 0; 00444 } 00445 if (use_re) 00446 { 00447 #if defined(HAVE_REGCOMP) 00448 result = 00449 regcomp (&elt_pattern, argv[1], 00450 REG_EXTENDED | REG_ICASE | REG_NOSUB); 00451 if (result) 00452 { 00453 char errorstring[128]; 00454 00455 regerror (result, &elt_pattern, errorstring, 128); 00456 Message (_("regexp error: %s\n"), errorstring); 00457 regfree (&elt_pattern); 00458 return (1); 00459 } 00460 #endif 00461 #if defined(HAVE_RE_COMP) 00462 if ((elt_pattern = re_comp (argv[1])) != NULL) 00463 { 00464 Message (_("re_comp error: %s\n"), elt_pattern); 00465 return (false); 00466 } 00467 #endif 00468 } 00469 } 00470 #endif 00471 00472 for (i = PCB->NetlistLib.MenuN-1; i >= 0; i--) 00473 { 00474 net = PCB->NetlistLib.Menu + i; 00475 00476 if (argc > 1) 00477 { 00478 #if defined(USE_RE) 00479 if (use_re) 00480 { 00481 #if defined(HAVE_REGCOMP) 00482 if (regexec (&elt_pattern, net->Name + 2, 1, &match, 0) != 0) 00483 continue; 00484 #endif 00485 #if defined(HAVE_RE_COMP) 00486 if (re_exec (net->Name + 2) != 1) 00487 continue; 00488 #endif 00489 } 00490 else 00491 #endif 00492 if (strcasecmp (net->Name + 2, argv[1])) 00493 continue; 00494 } 00495 net_found = 1; 00496 00497 pin = 0; 00498 if (func == (void *)netlist_style) 00499 { 00500 netlist_style (net, ARG(2)); 00501 } 00502 else if (argc > 2) 00503 { 00504 int l = strlen (argv[2]); 00505 for (j = net->EntryN-1; j >= 0 ; j--) 00506 if (strcasecmp (net->Entry[j].ListEntry, argv[2]) == 0 00507 || (strncasecmp (net->Entry[j].ListEntry, argv[2], l) == 0 00508 && net->Entry[j].ListEntry[l] == '-')) 00509 { 00510 pin = net->Entry + j; 00511 pin_found = 1; 00512 func (net, pin); 00513 } 00514 } 00515 else 00516 func (net, 0); 00517 } 00518 00519 if (argc > 2 && !pin_found) 00520 { 00521 gui->log ("Net %s has no pin %s\n", argv[1], argv[2]); 00522 return 1; 00523 } 00524 else if (!net_found) 00525 { 00526 gui->log ("No net named %s\n", argv[1]); 00527 } 00528 #ifdef HAVE_REGCOMP 00529 if (use_re) 00530 regfree (&elt_pattern); 00531 #endif 00532 00533 return 0; 00534 } 00535 00536 HID_Action netlist_action_list[] = { 00537 {"net", 0, Netlist, 00538 netlist_help, netlist_syntax} 00539 , 00540 {"netlist", 0, Netlist, 00541 netlist_help, netlist_syntax} 00542 }; 00543 00544 REGISTER_ACTIONS (netlist_action_list)