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
42 #include <sys/types.h>
46 #include "globalconst.h"
52 #ifdef HAVE_LIBDMALLOC
56 /* Because all the macros expect it, that's why. */
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.
74 /* This is the bit that we're setting. */
77 /* The name used in the output file. */
80 #define N(x) x, sizeof(x)-1
82 /* If set, this entry won't be output unless the object type is one
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 },
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).
153 static int bufptr
= 0;
157 #define B buffers[bufptr]
159 bufptr
= (bufptr
+ 1) % 10;
163 B
.ptr
= (char *) realloc (B
.ptr
, len
);
165 B
.ptr
= (char *) malloc (len
);
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;
183 grow_layer_list (int num
)
187 layers
= (char *) calloc (num
> 0 ? num
: 1, 1);
190 else if (num
> max_layers
)
193 layers
= (char *) realloc (layers
, max_layers
);
195 if (num
> num_layers
)
196 memset (layers
+ num_layers
, 0, num
- num_layers
- 1);
202 set_layer_list (int layer
, int v
)
204 if (layer
>= num_layers
)
205 grow_layer_list (layer
+ 1);
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
225 /* Returns a pointer to the first character past the list. */
227 parse_layer_list (const char *bp
, int (*error
) (const char *))
229 const char *orig_bp
= bp
;
230 int l
= 0, range
= -1;
244 else if (*bp
== ')' || *bp
== ',' || *bp
== '-')
249 set_layer_list (range
++, value
);
258 else if (isdigit ((int) *bp
))
259 l
= l
* 10 + (*bp
- '0');
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
);
278 /* Number of character the value "i" requires when printed. */
280 printed_int_length (int i
, int j
)
285 return 1 + (j
? 1 : 0);
287 return 2 + (j
? 1 : 0);
289 for (rv
= 1; i
>= 10; rv
++)
291 return rv
+ (j
? 1 : 0);
294 /* Returns a pointer to an internal buffer which is overwritten with
299 static char *buf
= 0;
300 static int buflen
= 0;
305 for (i
= 0; i
< num_layers
; i
++)
307 len
+= 1 + printed_int_length (i
, layers
[i
]);
311 buf
= (char *) realloc (buf
, len
);
313 buf
= (char *) malloc (len
);
320 for (i
= 0; i
< num_layers
; i
++)
325 for (j
= i
+ 1; j
< num_layers
&& layers
[j
] == 1; j
++)
329 sprintf (bp
, "%d-%d,", i
, j
- 1);
336 sprintf (bp
, "%d,", i
);
339 sprintf (bp
, "%d+,", i
);
342 sprintf (bp
, "%dS,", i
);
345 sprintf (bp
, "%dX,", i
);
349 sprintf (bp
, "%dt,", i
);
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
369 error_ignore (const char *msg
)
373 static FlagType empty_flags
;
376 common_string_to_flags (const char *flagstring
,
377 int (*error
) (const char *msg
),
378 FlagBitsType
*flagbits
,
386 rv
.Flags
= empty_flags
;
389 error
= error_ignore
;
391 if (flagstring
== NULL
)
394 fp
= ep
= flagstring
;
399 while (*ep
&& *ep
!= '"')
403 for (ep
= fp
; *ep
&& *ep
!= ',' && *ep
!= '"' && *ep
!= '('; 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
++)
413 ASSIGN_THERM (i
, layers
[i
], &rv
);
417 for (i
= 0; i
< n_flagbits
; i
++)
418 if (flagbits
[i
].nlen
== flen
419 && memcmp (flagbits
[i
].name
, fp
, flen
) == 0)
422 SET_FLAG (flagbits
[i
].mask
, &rv
);
427 const char *fmt
= "Unknown flag: \"%.*s\" ignored";
428 char *msg
= alloc_buf (strlen (fmt
) + flen
);
429 sprintf (msg
, fmt
, flen
, fp
);
439 string_to_flags (const char *flagstring
,
440 int (*error
) (const char *msg
))
442 return common_string_to_flags (flagstring
,
445 ENTRIES (object_flagbits
));
449 string_to_pcbflags (const char *flagstring
,
450 int (*error
) (const char *msg
))
452 return common_string_to_flags (flagstring
,
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.
471 common_flags_to_string (FlagType flags
,
473 FlagBitsType
*flagbits
,
478 FlagHolder fh
, savef
;
487 CLEAR_FLAG (VIAFLAG
, &fh
);
490 CLEAR_FLAG (RATFLAG
, &fh
);
493 CLEAR_FLAG (PINFLAG
, &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);
522 for (i
= 0; i
< n_flagbits
; i
++)
523 if (flagbits
[i
].object_types
& object_type
524 && (TEST_FLAG (flagbits
[i
].mask
, &fh
)))
528 strcpy (bp
, flagbits
[i
].name
);
529 bp
+= flagbits
[i
].nlen
;
530 CLEAR_FLAG (flagbits
[i
].mask
, &fh
);
533 if (TEST_ANY_THERMS (&fh
))
537 strcpy (bp
, "thermal");
538 bp
+= strlen ("thermal");
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 ());
553 flags_to_string (FlagType flags
, int object_type
)
555 return common_flags_to_string (flags
,
558 ENTRIES (object_flagbits
));
562 pcbflags_to_string (FlagType flags
)
564 return common_flags_to_string (flags
,
567 ENTRIES (pcb_flagbits
));
573 dump_flag (FlagType
* f
)
576 printf ("F:%08x T:[", f
->f
);
577 for (l
= 0; l
< (MAX_LAYER
+ 7) / 8; l
++)
578 printf (" %02x", f
->t
[l
]);
584 mem_any_set (unsigned char *ptr
, int bytes
)
594 * This exists for standalone testing of this file.
596 * Compile as: gcc -DHAVE_CONFIG_H -DFLAG_TEST strflags.c -o strflags.x -I..
605 int errors
= 0, count
= 0;
608 srandom ((unsigned int) now
+ getpid ());
611 for (i
= 0; i
< 16; i
++)
615 if (i
!= 1 && i
!= 4 && i
!= 5 && i
!= 9)
616 set_layer_list (i
, 1);
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
]);
627 while (count
< 1000000)
636 fh
.Flags
= empty_flags
;
637 for (i
= 0; i
< ENTRIES (object_flagbits
); i
++)
639 if (TEST_FLAG (object_flagbits
[i
].mask
, &fh
))
641 if ((otype
& object_flagbits
[i
].object_types
) == 0)
643 if ((random () & 4) == 0)
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
++)
653 ASSIGN_THERM (i
, 3, &fh
);
655 str
= flags_to_string (fh
.Flags
, otype
);
656 new_flags
= string_to_flags (str
, 0);
659 if (FLAGS_EQUAL (fh
.Flags
, new_flags
))
662 dump_flag (&fh
.Flags
);
664 dump_flag (&new_flags
);
670 while (count
< 1000000)
679 fh
.Flags
= empty_flags
;
680 for (i
= 0; i
< ENTRIES (pcb_flagbits
); i
++)
682 if (TEST_FLAG (pcb_flagbits
[i
].mask
, &fh
))
684 if ((random () & 4) == 0)
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);
695 if (FLAGS_EQUAL (fh
.Flags
, new_flags
))
698 dump_flag (&fh
.Flags
);
700 dump_flag (&new_flags
);
705 printf ("%d out of %d failed\n", errors
, count
);