Introduce POLYGONHOLE_MODE for creating holes in polygons
[geda-pcb/gde.git] / src / strflags.c
blobac1fdcc43bb50ecbecbd898dbd6823bf57f7f5ea
1 /* $Id$ */
2 /*
3 * COPYRIGHT
5 * PCB, interactive printed circuit board design
6 * Copyright (C) 2005 DJ Delorie
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * Contact addresses for paper mail and Email:
23 * DJ Delorie, 334 North Road, Deerfield NH 03037-1110, USA
24 * dj@delorie.com
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
32 #include <stdio.h>
33 #include <ctype.h>
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #endif
41 #ifdef FLAG_TEST
42 #include <time.h>
43 #include <sys/types.h>
44 #include <unistd.h>
45 #endif
47 #include "globalconst.h"
48 #include "global.h"
49 #include "compat.h"
50 #include "const.h"
51 #include "strflags.h"
53 #ifdef HAVE_LIBDMALLOC
54 #include <dmalloc.h>
55 #endif
57 RCSID ("$Id$");
59 /* Because all the macros expect it, that's why. */
60 typedef struct
62 FlagType Flags;
63 } FlagHolder;
65 /* Be careful to list more specific flags first, followed by general
66 * flags, when two flags use the same bit. For example, "onsolder" is
67 * for elements only, while "auto" is for everything else. They use
68 * the same bit, but onsolder is listed first so that elements will
69 * use it and not auto.
71 * Thermals are handled separately, as they're layer-selective.
74 typedef struct
77 /* This is the bit that we're setting. */
78 int mask;
80 /* The name used in the output file. */
81 char *name;
82 int nlen;
83 #define N(x) x, sizeof(x)-1
85 /* If set, this entry won't be output unless the object type is one
86 of these. */
87 int object_types;
89 } FlagBitsType;
91 static FlagBitsType object_flagbits[] = {
92 { PINFLAG, N ("pin"), ALL_TYPES },
93 { VIAFLAG, N ("via"), ALL_TYPES },
94 { FOUNDFLAG, N ("found"), ALL_TYPES },
95 { HOLEFLAG, N ("hole"), PIN_TYPES },
96 { RATFLAG, N ("rat"), RATLINE_TYPE },
97 { PININPOLYFLAG, N ("pininpoly"), PIN_TYPES | PAD_TYPE },
98 { CLEARPOLYFLAG, N ("clearpoly"), POLYGON_TYPE },
99 { HIDENAMEFLAG, N ("hidename"), ELEMENT_TYPE },
100 { DISPLAYNAMEFLAG, N ("showname"), ELEMENT_TYPE },
101 { CLEARLINEFLAG, N ("clearline"), LINE_TYPE | ARC_TYPE | TEXT_TYPE },
102 { SELECTEDFLAG, N ("selected"), ALL_TYPES },
103 { ONSOLDERFLAG, N ("onsolder"), ELEMENT_TYPE | PAD_TYPE },
104 { AUTOFLAG, N ("auto"), ALL_TYPES },
105 { SQUAREFLAG, N ("square"), PIN_TYPES | PAD_TYPE },
106 { RUBBERENDFLAG, N ("rubberend"), LINE_TYPE | ARC_TYPE },
107 { WARNFLAG, N ("warn"), PIN_TYPES | PAD_TYPE },
108 { USETHERMALFLAG, N ("usetherm"), PIN_TYPES | LINE_TYPE | ARC_TYPE },
109 { OCTAGONFLAG, N ("octagon"), PIN_TYPES | PAD_TYPE },
110 { DRCFLAG, N ("drc"), ALL_TYPES },
111 { LOCKFLAG, N ("lock"), ALL_TYPES },
112 { EDGE2FLAG, N ("edge2"), ALL_TYPES },
113 { FULLPOLYFLAG, N ("fullpoly"), POLYGON_TYPE},
114 { NOPASTEFLAG, N ("nopaste"), PAD_TYPE }
117 static FlagBitsType pcb_flagbits[] = {
118 { SHOWNUMBERFLAG, N ("shownumber"), 1 },
119 { LOCALREFFLAG, N ("localref"), 1 },
120 { CHECKPLANESFLAG, N ("checkplanes"), 1 },
121 { SHOWDRCFLAG, N ("showdrc"), 1 },
122 { RUBBERBANDFLAG, N ("rubberband"), 1 },
123 { DESCRIPTIONFLAG, N ("description"), 1 },
124 { NAMEONPCBFLAG, N ("nameonpcb"), 1 },
125 { AUTODRCFLAG, N ("autodrc"), 1 },
126 { ALLDIRECTIONFLAG, N ("alldirection"), 1 },
127 { SWAPSTARTDIRFLAG, N ("swapstartdir"), 1 },
128 { UNIQUENAMEFLAG, N ("uniquename"), 1 },
129 { CLEARNEWFLAG, N ("clearnew"), 1 },
130 { NEWFULLPOLYFLAG, N ("newfullpoly"), 1 },
131 { SNAPPINFLAG, N ("snappin"), 1 },
132 { SHOWMASKFLAG, N ("showmask"), 1 },
133 { THINDRAWFLAG, N ("thindraw"), 1 },
134 { ORTHOMOVEFLAG, N ("orthomove"), 1 },
135 { LIVEROUTEFLAG, N ("liveroute"), 1 },
136 { THINDRAWPOLYFLAG, N ("thindrawpoly"), 1 },
137 { LOCKNAMESFLAG, N ("locknames"), 1 },
138 { ONLYNAMESFLAG, N ("onlynames"), 1 },
139 { HIDENAMESFLAG, N ("hidenames"), 1 },
142 #undef N
145 * This helper function maintains a small list of buffers which are
146 * used by flags_to_string(). Each buffer is allocated from the heap,
147 * but the caller must not free them (they get realloced when they're
148 * reused, but never completely freed).
151 static struct
153 char *ptr;
154 int len;
155 } buffers[10];
156 static int bufptr = 0;
157 static char *
158 alloc_buf (int len)
160 #define B buffers[bufptr]
161 len++;
162 bufptr = (bufptr + 1) % 10;
163 if (B.len < len)
165 if (B.ptr)
166 B.ptr = (char *) realloc (B.ptr, len);
167 else
168 B.ptr = (char *) malloc (len);
169 B.len = len;
171 return B.ptr;
172 #undef B
176 * This set of routines manages a list of layer-specific flags.
177 * Callers should call grow_layer_list(0) to reset the list, and
178 * set_layer_list(layer,1) to set bits in the layer list. The results
179 * are stored in layers[], which has num_layers valid entries.
182 static char *layers = 0;
183 static int max_layers = 0, num_layers = 0;
185 static void
186 grow_layer_list (int num)
188 if (layers == 0)
190 layers = (char *) calloc (num > 0 ? num : 1, 1);
191 max_layers = num;
193 else if (num > max_layers)
195 max_layers = num;
196 layers = (char *) realloc (layers, max_layers);
198 if (num > num_layers)
199 memset (layers + num_layers, 0, num - num_layers - 1);
200 num_layers = num;
201 return;
204 static inline void
205 set_layer_list (int layer, int v)
207 if (layer >= num_layers)
208 grow_layer_list (layer + 1);
209 layers[layer] = v;
213 * These next two convert between layer lists and strings.
214 * parse_layer_list() is passed a pointer to a string, and parses a
215 * list of integer which reflect layers to be flagged. It returns a
216 * pointer to the first character following the list. The syntax of
217 * the list is a paren-surrounded, comma-separated list of integers
218 * and/or pairs of integers separated by a dash (like "(1,2,3-7)").
219 * Spaces and other punctuation are not allowed. The results are
220 * stored in layers[] defined above.
222 * print_layer_list() does the opposite - it uses the flags set in
223 * layers[] to build a string that represents them, using the syntax
224 * above.
228 /* Returns a pointer to the first character past the list. */
229 static const char *
230 parse_layer_list (const char *bp, int (*error) (const char *))
232 const char *orig_bp = bp;
233 int l = 0, range = -1;
234 int value = 1;
236 grow_layer_list (0);
237 while (*bp)
239 if (*bp == '+')
240 value = 2;
241 else if (*bp == 'S')
242 value = 3;
243 else if (*bp == 'X')
244 value = 4;
245 else if (*bp == 't')
246 value = 5;
247 else if (*bp == ')' || *bp == ',' || *bp == '-')
249 if (range == -1)
250 range = l;
251 while (range <= l)
252 set_layer_list (range++, value);
253 if (*bp == '-')
254 range = l;
255 else
256 range = -1;
257 value = 1;
258 l = 0;
261 else if (isdigit ((int) *bp))
262 l = l * 10 + (*bp - '0');
264 else if (error)
266 char *fmt = "Syntax error parsing layer list \"%.*s\" at %c";
267 char *msg = alloc_buf (strlen (fmt) + strlen (orig_bp));
268 sprintf (msg, fmt, bp - orig_bp + 5, orig_bp, *bp);
269 error (msg);
270 error = NULL;
273 if (*bp == ')')
274 return bp + 1;
276 bp++;
278 return bp;
281 /* Number of character the value "i" requires when printed. */
282 static int
283 printed_int_length (int i, int j)
285 int rv;
287 if (i < 10)
288 return 1 + (j ? 1 : 0);
289 if (i < 100)
290 return 2 + (j ? 1 : 0);
292 for (rv = 1; i >= 10; rv++)
293 i /= 10;
294 return rv + (j ? 1 : 0);
297 /* Returns a pointer to an internal buffer which is overwritten with
298 each new call. */
299 static char *
300 print_layer_list ()
302 static char *buf = 0;
303 static int buflen = 0;
304 int len, i, j;
305 char *bp;
307 len = 2;
308 for (i = 0; i < num_layers; i++)
309 if (layers[i])
310 len += 1 + printed_int_length (i, layers[i]);
311 if (buflen < len)
313 if (buf)
314 buf = (char *) realloc (buf, len);
315 else
316 buf = (char *) malloc (len);
317 buflen = len;
320 bp = buf;
321 *bp++ = '(';
323 for (i = 0; i < num_layers; i++)
324 if (layers[i])
326 /* 0 0 1 1 1 0 0 */
327 /* i j */
328 for (j = i + 1; j < num_layers && layers[j] == 1; j++)
330 if (j > i + 2)
332 sprintf (bp, "%d-%d,", i, j - 1);
333 i = j - 1;
335 else
336 switch (layers[i])
338 case 1:
339 sprintf (bp, "%d,", i);
340 break;
341 case 2:
342 sprintf (bp, "%d+,", i);
343 break;
344 case 3:
345 sprintf (bp, "%dS,", i);
346 break;
347 case 4:
348 sprintf (bp, "%dX,", i);
349 break;
350 case 5:
351 default:
352 sprintf (bp, "%dt,", i);
353 break;
355 bp += strlen (bp);
357 bp[-1] = ')';
358 *bp = 0;
359 return buf;
363 * Ok, now the two entry points to this file. The first, string_to_flags,
364 * is passed a string (usually from parse_y.y) and returns a "set of flags".
365 * In theory, this can be anything, but for now it's just an integer. Later
366 * it might be a structure, for example.
368 * Currently, there is no error handling :-P
371 static int
372 error_ignore (const char *msg)
373 { /* do nothing */
374 return 0;
376 static FlagType empty_flags;
378 static FlagType
379 common_string_to_flags (const char *flagstring,
380 int (*error) (const char *msg),
381 FlagBitsType *flagbits,
382 int n_flagbits)
384 const char *fp, *ep;
385 int flen;
386 FlagHolder rv;
387 int i;
389 rv.Flags = empty_flags;
391 if (error == 0)
392 error = error_ignore;
394 if (flagstring == NULL)
395 return empty_flags;
397 fp = ep = flagstring;
399 if (*fp == '"')
400 ep = ++fp;
402 while (*ep && *ep != '"')
404 int found = 0;
406 for (ep = fp; *ep && *ep != ',' && *ep != '"' && *ep != '('; ep++)
408 flen = ep - fp;
409 if (*ep == '(')
410 ep = parse_layer_list (ep + 1, error);
412 if (flen == 7 && memcmp (fp, "thermal", 7) == 0)
414 for (i = 0; i < MAX_LAYER && i < num_layers; i++)
415 if (layers[i])
416 ASSIGN_THERM (i, layers[i], &rv);
418 else
420 for (i = 0; i < n_flagbits; i++)
421 if (flagbits[i].nlen == flen
422 && memcmp (flagbits[i].name, fp, flen) == 0)
424 found = 1;
425 SET_FLAG (flagbits[i].mask, &rv);
426 break;
428 if (!found)
430 const char *fmt = "Unknown flag: \"%.*s\" ignored";
431 char *msg = alloc_buf (strlen (fmt) + flen);
432 sprintf (msg, fmt, flen, fp);
433 error (msg);
436 fp = ep + 1;
438 return rv.Flags;
441 FlagType
442 string_to_flags (const char *flagstring,
443 int (*error) (const char *msg))
445 return common_string_to_flags (flagstring,
446 error,
447 object_flagbits,
448 ENTRIES (object_flagbits));
451 FlagType
452 string_to_pcbflags (const char *flagstring,
453 int (*error) (const char *msg))
455 return common_string_to_flags (flagstring,
456 error,
457 pcb_flagbits,
458 ENTRIES (pcb_flagbits));
463 * Given a set of flags for a given type of object, return a string
464 * which reflects those flags. The only requirement is that this
465 * string be parseable by string_to_flags.
467 * Note that this function knows a little about what kinds of flags
468 * will be automatically set by parsing, so it won't (for example)
469 * include the "via" flag for VIA_TYPEs because it knows those get
470 * forcibly set when vias are parsed.
473 static char *
474 common_flags_to_string (FlagType flags,
475 int object_type,
476 FlagBitsType *flagbits,
477 int n_flagbits)
479 int len;
480 int i;
481 FlagHolder fh, savef;
482 char *buf, *bp;
484 fh.Flags = flags;
486 #ifndef FLAG_TEST
487 switch (object_type)
489 case VIA_TYPE:
490 CLEAR_FLAG (VIAFLAG, &fh);
491 break;
492 case RATLINE_TYPE:
493 CLEAR_FLAG (RATFLAG, &fh);
494 break;
495 case PIN_TYPE:
496 CLEAR_FLAG (PINFLAG, &fh);
497 break;
499 #endif
501 savef = fh;
503 len = 3; /* for "()\0" */
504 for (i = 0; i < n_flagbits; i++)
505 if ((flagbits[i].object_types & object_type)
506 && (TEST_FLAG (flagbits[i].mask, &fh)))
508 len += flagbits[i].nlen + 1;
509 CLEAR_FLAG (flagbits[i].mask, &fh);
512 if (TEST_ANY_THERMS (&fh))
514 len += sizeof ("thermal()");
515 for (i = 0; i < MAX_LAYER; i++)
516 if (TEST_THERM (i, &fh))
517 len += printed_int_length (i, GET_THERM (i, &fh)) + 1;
520 bp = buf = alloc_buf (len + 2);
522 *bp++ = '"';
524 fh = savef;
525 for (i = 0; i < n_flagbits; i++)
526 if (flagbits[i].object_types & object_type
527 && (TEST_FLAG (flagbits[i].mask, &fh)))
529 if (bp != buf + 1)
530 *bp++ = ',';
531 strcpy (bp, flagbits[i].name);
532 bp += flagbits[i].nlen;
533 CLEAR_FLAG (flagbits[i].mask, &fh);
536 if (TEST_ANY_THERMS (&fh))
538 if (bp != buf + 1)
539 *bp++ = ',';
540 strcpy (bp, "thermal");
541 bp += strlen ("thermal");
542 grow_layer_list (0);
543 for (i = 0; i < MAX_LAYER; i++)
544 if (TEST_THERM (i, &fh))
545 set_layer_list (i, GET_THERM (i, &fh));
546 strcpy (bp, print_layer_list ());
547 bp += strlen (bp);
550 *bp++ = '"';
551 *bp = 0;
552 return buf;
555 char *
556 flags_to_string (FlagType flags, int object_type)
558 return common_flags_to_string (flags,
559 object_type,
560 object_flagbits,
561 ENTRIES (object_flagbits));
564 char *
565 pcbflags_to_string (FlagType flags)
567 return common_flags_to_string (flags,
568 ALL_TYPES,
569 pcb_flagbits,
570 ENTRIES (pcb_flagbits));
573 #if FLAG_TEST
575 static void
576 dump_flag (FlagType * f)
578 int l;
579 printf ("F:%08x T:[", f->f);
580 for (l = 0; l < (MAX_LAYER + 7) / 8; l++)
581 printf (" %02x", f->t[l]);
582 printf ("]");
587 mem_any_set (unsigned char *ptr, int bytes)
589 while (bytes--)
590 if (*ptr++)
591 return 1;
592 return 0;
597 * This exists for standalone testing of this file.
599 * Compile as: gcc -DHAVE_CONFIG_H -DFLAG_TEST strflags.c -o strflags.x -I..
600 * and then run it.
604 main ()
606 time_t now;
607 int i;
608 int errors = 0, count = 0;
610 time (&now);
611 srandom ((unsigned int) now + getpid ());
613 grow_layer_list (0);
614 for (i = 0; i < 16; i++)
616 int j;
617 char *p;
618 if (i != 1 && i != 4 && i != 5 && i != 9)
619 set_layer_list (i, 1);
620 else
621 set_layer_list (i, 0);
622 p = print_layer_list ();
623 printf ("%2d : %20s =", i, p);
624 parse_layer_list (p + 1, 0);
625 for (j = 0; j < num_layers; j++)
626 printf (" %d", layers[j]);
627 printf ("\n");
630 while (count < 1000000)
632 FlagHolder fh;
633 char *str;
634 FlagType new_flags;
635 int i;
636 int otype;
638 otype = ALL_TYPES;
639 fh.Flags = empty_flags;
640 for (i = 0; i < ENTRIES (object_flagbits); i++)
642 if (TEST_FLAG (object_flagbits[i].mask, &fh))
643 continue;
644 if ((otype & object_flagbits[i].object_types) == 0)
645 continue;
646 if ((random () & 4) == 0)
647 continue;
649 otype &= object_flagbits[i].object_types;
650 SET_FLAG (object_flagbits[i].mask, &fh);
653 if (otype & PIN_TYPES)
654 for (i = 0; i < MAX_LAYER; i++)
655 if (random () & 4)
656 ASSIGN_THERM (i, 3, &fh);
658 str = flags_to_string (fh.Flags, otype);
659 new_flags = string_to_flags (str, 0);
661 count++;
662 if (FLAGS_EQUAL (fh.Flags, new_flags))
663 continue;
665 dump_flag (&fh.Flags);
666 printf (" ");
667 dump_flag (&new_flags);
668 printf ("\n");
669 if (++errors == 5)
670 exit (1);
673 while (count < 1000000)
675 FlagHolder fh;
676 char *str;
677 FlagType new_flags;
678 int i;
679 int otype;
681 otype = ALL_TYPES;
682 fh.Flags = empty_flags;
683 for (i = 0; i < ENTRIES (pcb_flagbits); i++)
685 if (TEST_FLAG (pcb_flagbits[i].mask, &fh))
686 continue;
687 if ((random () & 4) == 0)
688 continue;
690 otype &= pcb_flagbits[i].object_types;
691 SET_FLAG (pcb_flagbits[i].mask, &fh);
694 str = pcbflags_to_string (fh.Flags);
695 new_flags = string_to_pcbflags (str, 0);
697 count++;
698 if (FLAGS_EQUAL (fh.Flags, new_flags))
699 continue;
701 dump_flag (&fh.Flags);
702 printf (" ");
703 dump_flag (&new_flags);
704 printf ("\n");
705 if (++errors == 5)
706 exit (1);
708 printf ("%d out of %d failed\n", errors, count);
709 return errors;
712 #endif