Remove calls to SaveFindFlag()
[geda-pcb/pcjc2.git] / src / strflags.c
blob3699c536faf4687581fac9ad2de4448d2f85335c
1 /*
2 * COPYRIGHT
4 * PCB, interactive printed circuit board design
5 * Copyright (C) 2005 DJ Delorie
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Contact addresses for paper mail and Email:
22 * DJ Delorie, 334 North Road, Deerfield NH 03037-1110, USA
23 * dj@delorie.com
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
31 #include <stdio.h>
32 #include <ctype.h>
33 #ifdef HAVE_STDLIB_H
34 #include <stdlib.h>
35 #endif
36 #ifdef HAVE_STRING_H
37 #include <string.h>
38 #endif
40 #ifdef FLAG_TEST
41 #include <time.h>
42 #include <sys/types.h>
43 #include <unistd.h>
44 #endif
46 #include "globalconst.h"
47 #include "global.h"
48 #include "compat.h"
49 #include "const.h"
50 #include "strflags.h"
52 #ifdef HAVE_LIBDMALLOC
53 #include <dmalloc.h>
54 #endif
56 /* Because all the macros expect it, that's why. */
57 typedef struct
59 FlagType Flags;
60 } FlagHolder;
62 /* Be careful to list more specific flags first, followed by general
63 * flags, when two flags use the same bit. For example, "onsolder" is
64 * for elements only, while "auto" is for everything else. They use
65 * the same bit, but onsolder is listed first so that elements will
66 * use it and not auto.
68 * Thermals are handled separately, as they're layer-selective.
71 typedef struct
74 /* This is the bit that we're setting. */
75 int mask;
77 /* The name used in the output file. */
78 char *name;
79 int nlen;
80 #define N(x) x, sizeof(x)-1
82 /* If set, this entry won't be output unless the object type is one
83 of these. */
84 int object_types;
86 } FlagBitsType;
88 static FlagBitsType object_flagbits[] = {
89 { PINFLAG, N ("pin"), ALL_TYPES },
90 { VIAFLAG, N ("via"), ALL_TYPES },
91 { FOUNDFLAG, N ("found"), ALL_TYPES },
92 { HOLEFLAG, N ("hole"), PIN_TYPES },
93 { RATFLAG, N ("rat"), RATLINE_TYPE },
94 { PININPOLYFLAG, N ("pininpoly"), PIN_TYPES | PAD_TYPE },
95 { CLEARPOLYFLAG, N ("clearpoly"), POLYGON_TYPE },
96 { HIDENAMEFLAG, N ("hidename"), ELEMENT_TYPE },
97 { DISPLAYNAMEFLAG, N ("showname"), ELEMENT_TYPE },
98 { CLEARLINEFLAG, N ("clearline"), LINE_TYPE | ARC_TYPE | TEXT_TYPE },
99 { SELECTEDFLAG, N ("selected"), ALL_TYPES },
100 { ONSOLDERFLAG, N ("onsolder"), ELEMENT_TYPE | PAD_TYPE | TEXT_TYPE },
101 { AUTOFLAG, N ("auto"), ALL_TYPES },
102 { SQUAREFLAG, N ("square"), PIN_TYPES | PAD_TYPE },
103 { RUBBERENDFLAG, N ("rubberend"), LINE_TYPE | ARC_TYPE },
104 { WARNFLAG, N ("warn"), PIN_TYPES | PAD_TYPE },
105 { USETHERMALFLAG, N ("usetherm"), PIN_TYPES | LINE_TYPE | ARC_TYPE },
106 { OCTAGONFLAG, N ("octagon"), PIN_TYPES | PAD_TYPE },
107 { DRCFLAG, N ("drc"), ALL_TYPES },
108 { LOCKFLAG, N ("lock"), ALL_TYPES },
109 { EDGE2FLAG, N ("edge2"), ALL_TYPES },
110 { FULLPOLYFLAG, N ("fullpoly"), POLYGON_TYPE},
111 { NOPASTEFLAG, N ("nopaste"), PAD_TYPE }
114 static FlagBitsType pcb_flagbits[] = {
115 { SHOWNUMBERFLAG, N ("shownumber"), 1 },
116 { LOCALREFFLAG, N ("localref"), 1 },
117 { CHECKPLANESFLAG, N ("checkplanes"), 1 },
118 { SHOWDRCFLAG, N ("showdrc"), 1 },
119 { RUBBERBANDFLAG, N ("rubberband"), 1 },
120 { DESCRIPTIONFLAG, N ("description"), 1 },
121 { NAMEONPCBFLAG, N ("nameonpcb"), 1 },
122 { AUTODRCFLAG, N ("autodrc"), 1 },
123 { ALLDIRECTIONFLAG, N ("alldirection"), 1 },
124 { SWAPSTARTDIRFLAG, N ("swapstartdir"), 1 },
125 { UNIQUENAMEFLAG, N ("uniquename"), 1 },
126 { CLEARNEWFLAG, N ("clearnew"), 1 },
127 { NEWFULLPOLYFLAG, N ("newfullpoly"), 1 },
128 { SNAPPINFLAG, N ("snappin"), 1 },
129 { SHOWMASKFLAG, N ("showmask"), 1 },
130 { THINDRAWFLAG, N ("thindraw"), 1 },
131 { ORTHOMOVEFLAG, N ("orthomove"), 1 },
132 { LIVEROUTEFLAG, N ("liveroute"), 1 },
133 { THINDRAWPOLYFLAG, N ("thindrawpoly"), 1 },
134 { LOCKNAMESFLAG, N ("locknames"), 1 },
135 { ONLYNAMESFLAG, N ("onlynames"), 1 },
136 { HIDENAMESFLAG, N ("hidenames"), 1 },
139 #undef N
142 * This helper function maintains a small list of buffers which are
143 * used by flags_to_string(). Each buffer is allocated from the heap,
144 * but the caller must not free them (they get realloced when they're
145 * reused, but never completely freed).
148 static struct
150 char *ptr;
151 int len;
152 } buffers[10];
153 static int bufptr = 0;
154 static char *
155 alloc_buf (int len)
157 #define B buffers[bufptr]
158 len++;
159 bufptr = (bufptr + 1) % 10;
160 if (B.len < len)
162 if (B.ptr)
163 B.ptr = (char *) realloc (B.ptr, len);
164 else
165 B.ptr = (char *) malloc (len);
166 B.len = len;
168 return B.ptr;
169 #undef B
173 * This set of routines manages a list of layer-specific flags.
174 * Callers should call grow_layer_list(0) to reset the list, and
175 * set_layer_list(layer,1) to set bits in the layer list. The results
176 * are stored in layers[], which has num_layers valid entries.
179 static char *layers = 0;
180 static int max_layers = 0, num_layers = 0;
182 static void
183 grow_layer_list (int num)
185 if (layers == 0)
187 layers = (char *) calloc (num > 0 ? num : 1, 1);
188 max_layers = num;
190 else if (num > max_layers)
192 max_layers = num;
193 layers = (char *) realloc (layers, max_layers);
195 if (num > num_layers)
196 memset (layers + num_layers, 0, num - num_layers - 1);
197 num_layers = num;
198 return;
201 static inline void
202 set_layer_list (int layer, int v)
204 if (layer >= num_layers)
205 grow_layer_list (layer + 1);
206 layers[layer] = v;
210 * These next two convert between layer lists and strings.
211 * parse_layer_list() is passed a pointer to a string, and parses a
212 * list of integer which reflect layers to be flagged. It returns a
213 * pointer to the first character following the list. The syntax of
214 * the list is a paren-surrounded, comma-separated list of integers
215 * and/or pairs of integers separated by a dash (like "(1,2,3-7)").
216 * Spaces and other punctuation are not allowed. The results are
217 * stored in layers[] defined above.
219 * print_layer_list() does the opposite - it uses the flags set in
220 * layers[] to build a string that represents them, using the syntax
221 * above.
225 /* Returns a pointer to the first character past the list. */
226 static const char *
227 parse_layer_list (const char *bp, int (*error) (const char *))
229 const char *orig_bp = bp;
230 int l = 0, range = -1;
231 int value = 1;
233 grow_layer_list (0);
234 while (*bp)
236 if (*bp == '+')
237 value = 2;
238 else if (*bp == 'S')
239 value = 3;
240 else if (*bp == 'X')
241 value = 4;
242 else if (*bp == 't')
243 value = 5;
244 else if (*bp == ')' || *bp == ',' || *bp == '-')
246 if (range == -1)
247 range = l;
248 while (range <= l)
249 set_layer_list (range++, value);
250 if (*bp == '-')
251 range = l;
252 else
253 range = -1;
254 value = 1;
255 l = 0;
258 else if (isdigit ((int) *bp))
259 l = l * 10 + (*bp - '0');
261 else if (error)
263 char *fmt = "Syntax error parsing layer list \"%.*s\" at %c";
264 char *msg = alloc_buf (strlen (fmt) + strlen (orig_bp));
265 sprintf (msg, fmt, bp - orig_bp + 5, orig_bp, *bp);
266 error (msg);
267 error = NULL;
270 if (*bp == ')')
271 return bp + 1;
273 bp++;
275 return bp;
278 /* Number of character the value "i" requires when printed. */
279 static int
280 printed_int_length (int i, int j)
282 int rv;
284 if (i < 10)
285 return 1 + (j ? 1 : 0);
286 if (i < 100)
287 return 2 + (j ? 1 : 0);
289 for (rv = 1; i >= 10; rv++)
290 i /= 10;
291 return rv + (j ? 1 : 0);
294 /* Returns a pointer to an internal buffer which is overwritten with
295 each new call. */
296 static char *
297 print_layer_list ()
299 static char *buf = 0;
300 static int buflen = 0;
301 int len, i, j;
302 char *bp;
304 len = 2;
305 for (i = 0; i < num_layers; i++)
306 if (layers[i])
307 len += 1 + printed_int_length (i, layers[i]);
308 if (buflen < len)
310 if (buf)
311 buf = (char *) realloc (buf, len);
312 else
313 buf = (char *) malloc (len);
314 buflen = len;
317 bp = buf;
318 *bp++ = '(';
320 for (i = 0; i < num_layers; i++)
321 if (layers[i])
323 /* 0 0 1 1 1 0 0 */
324 /* i j */
325 for (j = i + 1; j < num_layers && layers[j] == 1; j++)
327 if (j > i + 2)
329 sprintf (bp, "%d-%d,", i, j - 1);
330 i = j - 1;
332 else
333 switch (layers[i])
335 case 1:
336 sprintf (bp, "%d,", i);
337 break;
338 case 2:
339 sprintf (bp, "%d+,", i);
340 break;
341 case 3:
342 sprintf (bp, "%dS,", i);
343 break;
344 case 4:
345 sprintf (bp, "%dX,", i);
346 break;
347 case 5:
348 default:
349 sprintf (bp, "%dt,", i);
350 break;
352 bp += strlen (bp);
354 bp[-1] = ')';
355 *bp = 0;
356 return buf;
360 * Ok, now the two entry points to this file. The first, string_to_flags,
361 * is passed a string (usually from parse_y.y) and returns a "set of flags".
362 * In theory, this can be anything, but for now it's just an integer. Later
363 * it might be a structure, for example.
365 * Currently, there is no error handling :-P
368 static int
369 error_ignore (const char *msg)
370 { /* do nothing */
371 return 0;
373 static FlagType empty_flags;
375 static FlagType
376 common_string_to_flags (const char *flagstring,
377 int (*error) (const char *msg),
378 FlagBitsType *flagbits,
379 int n_flagbits)
381 const char *fp, *ep;
382 int flen;
383 FlagHolder rv;
384 int i;
386 rv.Flags = empty_flags;
388 if (error == 0)
389 error = error_ignore;
391 if (flagstring == NULL)
392 return empty_flags;
394 fp = ep = flagstring;
396 if (*fp == '"')
397 ep = ++fp;
399 while (*ep && *ep != '"')
401 int found = 0;
403 for (ep = fp; *ep && *ep != ',' && *ep != '"' && *ep != '('; ep++)
405 flen = ep - fp;
406 if (*ep == '(')
407 ep = parse_layer_list (ep + 1, error);
409 if (flen == 7 && memcmp (fp, "thermal", 7) == 0)
411 for (i = 0; i < MAX_LAYER && i < num_layers; i++)
412 if (layers[i])
413 ASSIGN_THERM (i, layers[i], &rv);
415 else
417 for (i = 0; i < n_flagbits; i++)
418 if (flagbits[i].nlen == flen
419 && memcmp (flagbits[i].name, fp, flen) == 0)
421 found = 1;
422 SET_FLAG (flagbits[i].mask, &rv);
423 break;
425 if (!found)
427 const char *fmt = "Unknown flag: \"%.*s\" ignored";
428 char *msg = alloc_buf (strlen (fmt) + flen);
429 sprintf (msg, fmt, flen, fp);
430 error (msg);
433 fp = ep + 1;
435 return rv.Flags;
438 FlagType
439 string_to_flags (const char *flagstring,
440 int (*error) (const char *msg))
442 return common_string_to_flags (flagstring,
443 error,
444 object_flagbits,
445 ENTRIES (object_flagbits));
448 FlagType
449 string_to_pcbflags (const char *flagstring,
450 int (*error) (const char *msg))
452 return common_string_to_flags (flagstring,
453 error,
454 pcb_flagbits,
455 ENTRIES (pcb_flagbits));
460 * Given a set of flags for a given type of object, return a string
461 * which reflects those flags. The only requirement is that this
462 * string be parseable by string_to_flags.
464 * Note that this function knows a little about what kinds of flags
465 * will be automatically set by parsing, so it won't (for example)
466 * include the "via" flag for VIA_TYPEs because it knows those get
467 * forcibly set when vias are parsed.
470 static char *
471 common_flags_to_string (FlagType flags,
472 int object_type,
473 FlagBitsType *flagbits,
474 int n_flagbits)
476 int len;
477 int i;
478 FlagHolder fh, savef;
479 char *buf, *bp;
481 fh.Flags = flags;
483 #ifndef FLAG_TEST
484 switch (object_type)
486 case VIA_TYPE:
487 CLEAR_FLAG (VIAFLAG, &fh);
488 break;
489 case RATLINE_TYPE:
490 CLEAR_FLAG (RATFLAG, &fh);
491 break;
492 case PIN_TYPE:
493 CLEAR_FLAG (PINFLAG, &fh);
494 break;
496 #endif
498 savef = fh;
500 len = 3; /* for "()\0" */
501 for (i = 0; i < n_flagbits; i++)
502 if ((flagbits[i].object_types & object_type)
503 && (TEST_FLAG (flagbits[i].mask, &fh)))
505 len += flagbits[i].nlen + 1;
506 CLEAR_FLAG (flagbits[i].mask, &fh);
509 if (TEST_ANY_THERMS (&fh))
511 len += sizeof ("thermal()");
512 for (i = 0; i < MAX_LAYER; i++)
513 if (TEST_THERM (i, &fh))
514 len += printed_int_length (i, GET_THERM (i, &fh)) + 1;
517 bp = buf = alloc_buf (len + 2);
519 *bp++ = '"';
521 fh = savef;
522 for (i = 0; i < n_flagbits; i++)
523 if (flagbits[i].object_types & object_type
524 && (TEST_FLAG (flagbits[i].mask, &fh)))
526 if (bp != buf + 1)
527 *bp++ = ',';
528 strcpy (bp, flagbits[i].name);
529 bp += flagbits[i].nlen;
530 CLEAR_FLAG (flagbits[i].mask, &fh);
533 if (TEST_ANY_THERMS (&fh))
535 if (bp != buf + 1)
536 *bp++ = ',';
537 strcpy (bp, "thermal");
538 bp += strlen ("thermal");
539 grow_layer_list (0);
540 for (i = 0; i < MAX_LAYER; i++)
541 if (TEST_THERM (i, &fh))
542 set_layer_list (i, GET_THERM (i, &fh));
543 strcpy (bp, print_layer_list ());
544 bp += strlen (bp);
547 *bp++ = '"';
548 *bp = 0;
549 return buf;
552 char *
553 flags_to_string (FlagType flags, int object_type)
555 return common_flags_to_string (flags,
556 object_type,
557 object_flagbits,
558 ENTRIES (object_flagbits));
561 char *
562 pcbflags_to_string (FlagType flags)
564 return common_flags_to_string (flags,
565 ALL_TYPES,
566 pcb_flagbits,
567 ENTRIES (pcb_flagbits));
570 #if FLAG_TEST
572 static void
573 dump_flag (FlagType * f)
575 int l;
576 printf ("F:%08x T:[", f->f);
577 for (l = 0; l < (MAX_LAYER + 7) / 8; l++)
578 printf (" %02x", f->t[l]);
579 printf ("]");
584 mem_any_set (unsigned char *ptr, int bytes)
586 while (bytes--)
587 if (*ptr++)
588 return 1;
589 return 0;
594 * This exists for standalone testing of this file.
596 * Compile as: gcc -DHAVE_CONFIG_H -DFLAG_TEST strflags.c -o strflags.x -I..
597 * and then run it.
601 main ()
603 time_t now;
604 int i;
605 int errors = 0, count = 0;
607 time (&now);
608 srandom ((unsigned int) now + getpid ());
610 grow_layer_list (0);
611 for (i = 0; i < 16; i++)
613 int j;
614 char *p;
615 if (i != 1 && i != 4 && i != 5 && i != 9)
616 set_layer_list (i, 1);
617 else
618 set_layer_list (i, 0);
619 p = print_layer_list ();
620 printf ("%2d : %20s =", i, p);
621 parse_layer_list (p + 1, 0);
622 for (j = 0; j < num_layers; j++)
623 printf (" %d", layers[j]);
624 printf ("\n");
627 while (count < 1000000)
629 FlagHolder fh;
630 char *str;
631 FlagType new_flags;
632 int i;
633 int otype;
635 otype = ALL_TYPES;
636 fh.Flags = empty_flags;
637 for (i = 0; i < ENTRIES (object_flagbits); i++)
639 if (TEST_FLAG (object_flagbits[i].mask, &fh))
640 continue;
641 if ((otype & object_flagbits[i].object_types) == 0)
642 continue;
643 if ((random () & 4) == 0)
644 continue;
646 otype &= object_flagbits[i].object_types;
647 SET_FLAG (object_flagbits[i].mask, &fh);
650 if (otype & PIN_TYPES)
651 for (i = 0; i < MAX_LAYER; i++)
652 if (random () & 4)
653 ASSIGN_THERM (i, 3, &fh);
655 str = flags_to_string (fh.Flags, otype);
656 new_flags = string_to_flags (str, 0);
658 count++;
659 if (FLAGS_EQUAL (fh.Flags, new_flags))
660 continue;
662 dump_flag (&fh.Flags);
663 printf (" ");
664 dump_flag (&new_flags);
665 printf ("\n");
666 if (++errors == 5)
667 exit (1);
670 while (count < 1000000)
672 FlagHolder fh;
673 char *str;
674 FlagType new_flags;
675 int i;
676 int otype;
678 otype = ALL_TYPES;
679 fh.Flags = empty_flags;
680 for (i = 0; i < ENTRIES (pcb_flagbits); i++)
682 if (TEST_FLAG (pcb_flagbits[i].mask, &fh))
683 continue;
684 if ((random () & 4) == 0)
685 continue;
687 otype &= pcb_flagbits[i].object_types;
688 SET_FLAG (pcb_flagbits[i].mask, &fh);
691 str = pcbflags_to_string (fh.Flags);
692 new_flags = string_to_pcbflags (str, 0);
694 count++;
695 if (FLAGS_EQUAL (fh.Flags, new_flags))
696 continue;
698 dump_flag (&fh.Flags);
699 printf (" ");
700 dump_flag (&new_flags);
701 printf ("\n");
702 if (++errors == 5)
703 exit (1);
705 printf ("%d out of %d failed\n", errors, count);
706 return errors;
709 #endif