pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00039 #ifdef HAVE_CONFIG_H 00040 #include "config.h" 00041 #endif 00042 00043 #include <stdio.h> 00044 #include <ctype.h> 00045 #ifdef HAVE_STDLIB_H 00046 #include <stdlib.h> 00047 #endif 00048 #ifdef HAVE_STRING_H 00049 #include <string.h> 00050 #endif 00051 00052 #include "globalconst.h" 00053 #include "global.h" 00054 #include "compat.h" 00055 #include "hid.h" 00056 #include "strflags.h" 00057 00058 #ifdef HAVE_LIBDMALLOC 00059 #include <dmalloc.h> 00060 #endif 00061 00062 /* Because all the macros expect it, that's why. */ 00063 typedef struct 00064 { 00065 FlagType Flags; 00066 } FlagHolder; 00067 00077 typedef struct 00078 { 00079 int mask; 00080 char *name; 00081 int nlen; 00082 #define N(x) x, sizeof(x)-1 00083 00084 int object_types; 00086 } FlagBitsType; 00087 00088 static FlagBitsType object_flagbits[] = { 00089 { PINFLAG, N ("pin"), ALL_TYPES }, 00090 { VIAFLAG, N ("via"), ALL_TYPES }, 00091 { FOUNDFLAG, N ("found"), ALL_TYPES }, 00092 { HOLEFLAG, N ("hole"), PIN_TYPES }, 00093 { RATFLAG, N ("rat"), RATLINE_TYPE }, 00094 { PININPOLYFLAG, N ("pininpoly"), PIN_TYPES | PAD_TYPE }, 00095 { CLEARPOLYFLAG, N ("clearpoly"), POLYGON_TYPE }, 00096 { HIDENAMEFLAG, N ("hidename"), ELEMENT_TYPE }, 00097 { DISPLAYNAMEFLAG, N ("showname"), ELEMENT_TYPE }, 00098 { CLEARLINEFLAG, N ("clearline"), LINE_TYPE | ARC_TYPE | TEXT_TYPE }, 00099 { SELECTEDFLAG, N ("selected"), ALL_TYPES }, 00100 { ONSOLDERFLAG, N ("onsolder"), ELEMENT_TYPE | PAD_TYPE | TEXT_TYPE | ELEMENTNAME_TYPE }, 00101 { AUTOFLAG, N ("auto"), ALL_TYPES }, 00102 { SQUAREFLAG, N ("square"), PIN_TYPES | PAD_TYPE }, 00103 { RUBBERENDFLAG, N ("rubberend"), LINE_TYPE | ARC_TYPE }, 00104 { WARNFLAG, N ("warn"), PIN_TYPES | PAD_TYPE }, 00105 { USETHERMALFLAG, N ("usetherm"), PIN_TYPES | LINE_TYPE | ARC_TYPE }, 00106 { OCTAGONFLAG, N ("octagon"), PIN_TYPES | PAD_TYPE }, 00107 { DRCFLAG, N ("drc"), ALL_TYPES }, 00108 { LOCKFLAG, N ("lock"), ALL_TYPES }, 00109 { EDGE2FLAG, N ("edge2"), ALL_TYPES }, 00110 { FULLPOLYFLAG, N ("fullpoly"), POLYGON_TYPE}, 00111 { NOPASTEFLAG, N ("nopaste"), PAD_TYPE }, 00112 { CONNECTEDFLAG, N ("connected"), ALL_TYPES } 00113 }; 00114 00115 static FlagBitsType pcb_flagbits[] = { 00116 { SHOWNUMBERFLAG, N ("shownumber"), ALL_TYPES }, 00117 { LOCALREFFLAG, N ("localref"), ALL_TYPES }, 00118 { CHECKPLANESFLAG, N ("checkplanes"), ALL_TYPES }, 00119 { SHOWDRCFLAG, N ("showdrc"), ALL_TYPES }, 00120 { RUBBERBANDFLAG, N ("rubberband"), ALL_TYPES }, 00121 { DESCRIPTIONFLAG, N ("description"), ALL_TYPES }, 00122 { NAMEONPCBFLAG, N ("nameonpcb"), ALL_TYPES }, 00123 { AUTODRCFLAG, N ("autodrc"), ALL_TYPES }, 00124 { ALLDIRECTIONFLAG, N ("alldirection"), ALL_TYPES }, 00125 { SWAPSTARTDIRFLAG, N ("swapstartdir"), ALL_TYPES }, 00126 { UNIQUENAMEFLAG, N ("uniquename"), ALL_TYPES }, 00127 { CLEARNEWFLAG, N ("clearnew"), ALL_TYPES }, 00128 { NEWFULLPOLYFLAG, N ("newfullpoly"), ALL_TYPES }, 00129 { SNAPPINFLAG, N ("snappin"), ALL_TYPES }, 00130 { SHOWMASKFLAG, N ("showmask"), ALL_TYPES }, 00131 { THINDRAWFLAG, N ("thindraw"), ALL_TYPES }, 00132 { ORTHOMOVEFLAG, N ("orthomove"), ALL_TYPES }, 00133 { LIVEROUTEFLAG, N ("liveroute"), ALL_TYPES }, 00134 { THINDRAWPOLYFLAG, N ("thindrawpoly"), ALL_TYPES }, 00135 { LOCKNAMESFLAG, N ("locknames"), ALL_TYPES }, 00136 { ONLYNAMESFLAG, N ("onlynames"), ALL_TYPES }, 00137 { HIDENAMESFLAG, N ("hidenames"), ALL_TYPES }, 00138 { AUTOBURIEDVIASFLAG, N ("autoburiedvias"), ALL_TYPES }, 00139 }; 00140 00141 #undef N 00142 00143 /* 00144 * This helper function maintains a small list of buffers which are 00145 * used by flags_to_string(). Each buffer is allocated from the heap, 00146 * but the caller must not free them (they get realloced when they're 00147 * reused, but never completely freed). 00148 */ 00149 00150 static struct 00151 { 00152 char *ptr; 00153 int len; 00154 } buffers[10]; 00155 static int bufptr = 0; 00156 static char * 00157 alloc_buf (int len) 00158 { 00159 #define B buffers[bufptr] 00160 len++; 00161 bufptr = (bufptr + 1) % 10; 00162 if (B.len < len) 00163 { 00164 if (B.ptr) 00165 B.ptr = (char *) realloc (B.ptr, len); 00166 else 00167 B.ptr = (char *) malloc (len); 00168 B.len = len; 00169 } 00170 return B.ptr; 00171 #undef B 00172 } 00173 00174 void 00175 uninit_strflags_buf (void) 00176 { 00177 int n; 00178 for (n = 0; n < 10; n++) 00179 { 00180 if (buffers[n].ptr != NULL) 00181 { 00182 free (buffers[n].ptr); 00183 buffers[n].ptr = NULL; 00184 } 00185 } 00186 } 00187 00188 static char *layers = 0; 00189 static int max_layers = 0, num_layers = 0; 00190 00202 static void 00203 grow_layer_list (int num) 00204 { 00205 if (layers == 0) 00206 { 00207 layers = (char *) calloc (num > 0 ? num : 1, 1); 00208 max_layers = num; 00209 } 00210 else if (num > max_layers) 00211 { 00212 max_layers = num; 00213 layers = (char *) realloc (layers, max_layers); 00214 } 00215 if (num > num_layers) 00216 memset (layers + num_layers, 0, num - num_layers - 1); 00217 num_layers = num; 00218 return; 00219 } 00220 00221 void 00222 uninit_strflags_layerlist (void) 00223 { 00224 if (layers != NULL) 00225 { 00226 free (layers); 00227 layers = NULL; 00228 num_layers = max_layers = 0; 00229 } 00230 } 00231 00243 static inline void 00244 set_layer_list (int layer, int v) 00245 { 00246 if (layer >= num_layers) 00247 grow_layer_list (layer + 1); 00248 layers[layer] = v; 00249 } 00250 00269 static const char * 00270 parse_layer_list (const char *bp, int (*error) (const char *)) 00271 { 00272 const char *orig_bp = bp; 00273 int l = 0, range = -1; 00274 int value = 1; 00275 00276 grow_layer_list (0); 00277 while (*bp) 00278 { 00279 if (*bp == '+') 00280 value = 2; 00281 else if (*bp == 'S') 00282 value = 3; 00283 else if (*bp == 'X') 00284 value = 4; 00285 else if (*bp == 't') 00286 value = 5; 00287 else if (*bp == ')' || *bp == ',' || *bp == '-') 00288 { 00289 if (range == -1) 00290 range = l; 00291 while (range <= l) 00292 set_layer_list (range++, value); 00293 if (*bp == '-') 00294 range = l; 00295 else 00296 range = -1; 00297 value = 1; 00298 l = 0; 00299 } 00300 00301 else if (isdigit ((int) *bp)) 00302 l = l * 10 + (*bp - '0'); 00303 00304 else if (error) 00305 { 00306 char *fmt = "Syntax error parsing layer list \"%.*s\" at %c"; 00307 char *msg = alloc_buf (strlen (fmt) + strlen (orig_bp)); 00308 sprintf (msg, fmt, bp - orig_bp + 5, orig_bp, *bp); 00309 error (msg); 00310 error = NULL; 00311 } 00312 00313 if (*bp == ')') 00314 return bp + 1; 00315 00316 bp++; 00317 } 00318 return bp; 00319 } 00320 00324 static int 00325 printed_int_length (int i, int j) 00326 { 00327 int rv; 00328 00329 if (i < 10) 00330 return 1 + (j ? 1 : 0); 00331 if (i < 100) 00332 return 2 + (j ? 1 : 0); 00333 00334 for (rv = 1; i >= 10; rv++) 00335 i /= 10; 00336 return rv + (j ? 1 : 0); 00337 } 00338 00354 static char * 00355 print_layer_list () 00356 { 00357 static char *buf = 0; 00358 static int buflen = 0; 00359 int len, i, j; 00360 char *bp; 00361 00362 len = 2; 00363 for (i = 0; i < num_layers; i++) 00364 if (layers[i]) 00365 len += 1 + printed_int_length (i, layers[i]); 00366 if (buflen < len) 00367 { 00368 if (buf) 00369 buf = (char *) realloc (buf, len); 00370 else 00371 buf = (char *) malloc (len); 00372 buflen = len; 00373 } 00374 00375 bp = buf; 00376 *bp++ = '('; 00377 00378 for (i = 0; i < num_layers; i++) 00379 if (layers[i]) 00380 { 00381 /* 0 0 1 1 1 0 0 */ 00382 /* i j */ 00383 for (j = i + 1; j < num_layers && layers[j] == 1; j++) 00384 ; 00385 if (j > i + 2) 00386 { 00387 sprintf (bp, "%d-%d,", i, j - 1); 00388 i = j - 1; 00389 } 00390 else 00391 switch (layers[i]) 00392 { 00393 case 1: 00394 sprintf (bp, "%d,", i); 00395 break; 00396 case 2: 00397 sprintf (bp, "%d+,", i); 00398 break; 00399 case 3: 00400 sprintf (bp, "%dS,", i); 00401 break; 00402 case 4: 00403 sprintf (bp, "%dX,", i); 00404 break; 00405 case 5: 00406 default: 00407 sprintf (bp, "%dt,", i); 00408 break; 00409 } 00410 bp += strlen (bp); 00411 } 00412 bp[-1] = ')'; 00413 *bp = 0; 00414 return buf; 00415 } 00416 00417 static int 00418 error_ignore (const char *msg) 00419 { /* do nothing */ 00420 return 0; 00421 } 00422 static FlagType empty_flags; 00423 00424 static FlagType 00425 common_string_to_flags (const char *flagstring, 00426 int (*error) (const char *msg), 00427 FlagBitsType *flagbits, 00428 int n_flagbits) 00429 { 00430 const char *fp, *ep; 00431 int flen; 00432 FlagHolder rv; 00433 int i; 00434 00435 rv.Flags = empty_flags; 00436 00437 if (error == 0) 00438 error = error_ignore; 00439 00440 if (flagstring == NULL) 00441 return empty_flags; 00442 00443 fp = ep = flagstring; 00444 00445 if (*fp == '"') 00446 ep = ++fp; 00447 00448 while (*ep && *ep != '"') 00449 { 00450 int found = 0; 00451 00452 for (ep = fp; *ep && *ep != ',' && *ep != '"' && *ep != '('; ep++) 00453 ; 00454 flen = ep - fp; 00455 if (*ep == '(') 00456 ep = parse_layer_list (ep + 1, error); 00457 00458 if (flen == 7 && memcmp (fp, "thermal", 7) == 0) 00459 { 00460 for (i = 0; i < MAX_LAYER && i < num_layers; i++) 00461 if (layers[i]) 00462 ASSIGN_THERM (i, layers[i], &rv); 00463 } 00464 else 00465 { 00466 for (i = 0; i < n_flagbits; i++) 00467 if (flagbits[i].nlen == flen 00468 && memcmp (flagbits[i].name, fp, flen) == 0) 00469 { 00470 found = 1; 00471 SET_FLAG (flagbits[i].mask, &rv); 00472 break; 00473 } 00474 if (!found) 00475 { 00476 const char *fmt = "Unknown flag: \"%.*s\" ignored"; 00477 char *msg = alloc_buf (strlen (fmt) + flen); 00478 sprintf (msg, fmt, flen, fp); 00479 error (msg); 00480 } 00481 } 00482 fp = ep + 1; 00483 } 00484 return rv.Flags; 00485 } 00486 00496 FlagType 00497 string_to_flags (const char *flagstring, 00498 int (*error) (const char *msg)) 00499 { 00500 return common_string_to_flags (flagstring, 00501 error, 00502 object_flagbits, 00503 ENTRIES (object_flagbits)); 00504 } 00505 00515 FlagType 00516 string_to_pcbflags (const char *flagstring, 00517 int (*error) (const char *msg)) 00518 { 00519 return common_string_to_flags (flagstring, 00520 error, 00521 pcb_flagbits, 00522 ENTRIES (pcb_flagbits)); 00523 } 00524 00540 static char * 00541 common_flags_to_string (FlagType flags, 00542 int object_type, 00543 FlagBitsType *flagbits, 00544 int n_flagbits) 00545 { 00546 int len; 00547 int i; 00548 FlagHolder fh, savef; 00549 char *buf, *bp; 00550 00551 fh.Flags = flags; 00552 00553 switch (object_type) 00554 { 00555 case VIA_TYPE: 00556 CLEAR_FLAG (VIAFLAG, &fh); 00557 break; 00558 case RATLINE_TYPE: 00559 CLEAR_FLAG (RATFLAG, &fh); 00560 break; 00561 case PIN_TYPE: 00562 CLEAR_FLAG (PINFLAG, &fh); 00563 break; 00564 } 00565 00566 savef = fh; 00567 00568 len = 3; /* for "()\0" */ 00569 for (i = 0; i < n_flagbits; i++) 00570 if ((flagbits[i].object_types & object_type) 00571 && (TEST_FLAG (flagbits[i].mask, &fh))) 00572 { 00573 len += flagbits[i].nlen + 1; 00574 CLEAR_FLAG (flagbits[i].mask, &fh); 00575 } 00576 00577 if (TEST_ANY_THERMS (&fh)) 00578 { 00579 len += sizeof ("thermal()"); 00580 for (i = 0; i < MAX_LAYER; i++) 00581 if (TEST_THERM (i, &fh)) 00582 len += printed_int_length (i, GET_THERM (i, &fh)) + 1; 00583 } 00584 00585 bp = buf = alloc_buf (len + 2); 00586 00587 *bp++ = '"'; 00588 00589 fh = savef; 00590 for (i = 0; i < n_flagbits; i++) 00591 if (flagbits[i].object_types & object_type 00592 && (TEST_FLAG (flagbits[i].mask, &fh))) 00593 { 00594 if (bp != buf + 1) 00595 *bp++ = ','; 00596 strcpy (bp, flagbits[i].name); 00597 bp += flagbits[i].nlen; 00598 CLEAR_FLAG (flagbits[i].mask, &fh); 00599 } 00600 00601 if (TEST_ANY_THERMS (&fh)) 00602 { 00603 if (bp != buf + 1) 00604 *bp++ = ','; 00605 strcpy (bp, "thermal"); 00606 bp += strlen ("thermal"); 00607 grow_layer_list (0); 00608 for (i = 0; i < MAX_LAYER; i++) 00609 if (TEST_THERM (i, &fh)) 00610 set_layer_list (i, GET_THERM (i, &fh)); 00611 strcpy (bp, print_layer_list ()); 00612 bp += strlen (bp); 00613 } 00614 00615 *bp++ = '"'; 00616 *bp = 0; 00617 return buf; 00618 } 00619 00628 char * 00629 flags_to_string (FlagType flags, int object_type) 00630 { 00631 return common_flags_to_string (flags, 00632 object_type, 00633 object_flagbits, 00634 ENTRIES (object_flagbits)); 00635 } 00636 00640 char * 00641 pcbflags_to_string (FlagType flags) 00642 { 00643 return common_flags_to_string (flags, 00644 ALL_TYPES, 00645 pcb_flagbits, 00646 ENTRIES (pcb_flagbits)); 00647 }