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
43 #include <sys/types.h>
47 #include "globalconst.h"
53 #ifdef HAVE_LIBDMALLOC
59 /* Because all the macros expect it, that's why. */
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.
77 /* This is the bit that we're setting. */
80 /* The name used in the output file. */
83 #define N(x) x, sizeof(x)-1
85 /* If set, this entry won't be output unless the object type is one
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 },
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).
156 static int bufptr
= 0;
160 #define B buffers[bufptr]
162 bufptr
= (bufptr
+ 1) % 10;
166 B
.ptr
= (char *) realloc (B
.ptr
, len
);
168 B
.ptr
= (char *) malloc (len
);
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;
186 grow_layer_list (int num
)
190 layers
= (char *) calloc (num
> 0 ? num
: 1, 1);
193 else if (num
> max_layers
)
196 layers
= (char *) realloc (layers
, max_layers
);
198 if (num
> num_layers
)
199 memset (layers
+ num_layers
, 0, num
- num_layers
- 1);
205 set_layer_list (int layer
, int v
)
207 if (layer
>= num_layers
)
208 grow_layer_list (layer
+ 1);
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
228 /* Returns a pointer to the first character past the list. */
230 parse_layer_list (const char *bp
, int (*error
) (const char *))
232 const char *orig_bp
= bp
;
233 int l
= 0, range
= -1;
247 else if (*bp
== ')' || *bp
== ',' || *bp
== '-')
252 set_layer_list (range
++, value
);
261 else if (isdigit ((int) *bp
))
262 l
= l
* 10 + (*bp
- '0');
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
);
281 /* Number of character the value "i" requires when printed. */
283 printed_int_length (int i
, int j
)
288 return 1 + (j
? 1 : 0);
290 return 2 + (j
? 1 : 0);
292 for (rv
= 1; i
>= 10; rv
++)
294 return rv
+ (j
? 1 : 0);
297 /* Returns a pointer to an internal buffer which is overwritten with
302 static char *buf
= 0;
303 static int buflen
= 0;
308 for (i
= 0; i
< num_layers
; i
++)
310 len
+= 1 + printed_int_length (i
, layers
[i
]);
314 buf
= (char *) realloc (buf
, len
);
316 buf
= (char *) malloc (len
);
323 for (i
= 0; i
< num_layers
; i
++)
328 for (j
= i
+ 1; j
< num_layers
&& layers
[j
] == 1; j
++)
332 sprintf (bp
, "%d-%d,", i
, j
- 1);
339 sprintf (bp
, "%d,", i
);
342 sprintf (bp
, "%d+,", i
);
345 sprintf (bp
, "%dS,", i
);
348 sprintf (bp
, "%dX,", i
);
352 sprintf (bp
, "%dt,", i
);
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
372 error_ignore (const char *msg
)
376 static FlagType empty_flags
;
379 common_string_to_flags (const char *flagstring
,
380 int (*error
) (const char *msg
),
381 FlagBitsType
*flagbits
,
389 rv
.Flags
= empty_flags
;
392 error
= error_ignore
;
394 if (flagstring
== NULL
)
397 fp
= ep
= flagstring
;
402 while (*ep
&& *ep
!= '"')
406 for (ep
= fp
; *ep
&& *ep
!= ',' && *ep
!= '"' && *ep
!= '('; 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
++)
416 ASSIGN_THERM (i
, layers
[i
], &rv
);
420 for (i
= 0; i
< n_flagbits
; i
++)
421 if (flagbits
[i
].nlen
== flen
422 && memcmp (flagbits
[i
].name
, fp
, flen
) == 0)
425 SET_FLAG (flagbits
[i
].mask
, &rv
);
430 const char *fmt
= "Unknown flag: \"%.*s\" ignored";
431 char *msg
= alloc_buf (strlen (fmt
) + flen
);
432 sprintf (msg
, fmt
, flen
, fp
);
442 string_to_flags (const char *flagstring
,
443 int (*error
) (const char *msg
))
445 return common_string_to_flags (flagstring
,
448 ENTRIES (object_flagbits
));
452 string_to_pcbflags (const char *flagstring
,
453 int (*error
) (const char *msg
))
455 return common_string_to_flags (flagstring
,
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.
474 common_flags_to_string (FlagType flags
,
476 FlagBitsType
*flagbits
,
481 FlagHolder fh
, savef
;
490 CLEAR_FLAG (VIAFLAG
, &fh
);
493 CLEAR_FLAG (RATFLAG
, &fh
);
496 CLEAR_FLAG (PINFLAG
, &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);
525 for (i
= 0; i
< n_flagbits
; i
++)
526 if (flagbits
[i
].object_types
& object_type
527 && (TEST_FLAG (flagbits
[i
].mask
, &fh
)))
531 strcpy (bp
, flagbits
[i
].name
);
532 bp
+= flagbits
[i
].nlen
;
533 CLEAR_FLAG (flagbits
[i
].mask
, &fh
);
536 if (TEST_ANY_THERMS (&fh
))
540 strcpy (bp
, "thermal");
541 bp
+= strlen ("thermal");
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 ());
556 flags_to_string (FlagType flags
, int object_type
)
558 return common_flags_to_string (flags
,
561 ENTRIES (object_flagbits
));
565 pcbflags_to_string (FlagType flags
)
567 return common_flags_to_string (flags
,
570 ENTRIES (pcb_flagbits
));
576 dump_flag (FlagType
* f
)
579 printf ("F:%08x T:[", f
->f
);
580 for (l
= 0; l
< (MAX_LAYER
+ 7) / 8; l
++)
581 printf (" %02x", f
->t
[l
]);
587 mem_any_set (unsigned char *ptr
, int bytes
)
597 * This exists for standalone testing of this file.
599 * Compile as: gcc -DHAVE_CONFIG_H -DFLAG_TEST strflags.c -o strflags.x -I..
608 int errors
= 0, count
= 0;
611 srandom ((unsigned int) now
+ getpid ());
614 for (i
= 0; i
< 16; i
++)
618 if (i
!= 1 && i
!= 4 && i
!= 5 && i
!= 9)
619 set_layer_list (i
, 1);
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
]);
630 while (count
< 1000000)
639 fh
.Flags
= empty_flags
;
640 for (i
= 0; i
< ENTRIES (object_flagbits
); i
++)
642 if (TEST_FLAG (object_flagbits
[i
].mask
, &fh
))
644 if ((otype
& object_flagbits
[i
].object_types
) == 0)
646 if ((random () & 4) == 0)
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
++)
656 ASSIGN_THERM (i
, 3, &fh
);
658 str
= flags_to_string (fh
.Flags
, otype
);
659 new_flags
= string_to_flags (str
, 0);
662 if (FLAGS_EQUAL (fh
.Flags
, new_flags
))
665 dump_flag (&fh
.Flags
);
667 dump_flag (&new_flags
);
673 while (count
< 1000000)
682 fh
.Flags
= empty_flags
;
683 for (i
= 0; i
< ENTRIES (pcb_flagbits
); i
++)
685 if (TEST_FLAG (pcb_flagbits
[i
].mask
, &fh
))
687 if ((random () & 4) == 0)
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);
698 if (FLAGS_EQUAL (fh
.Flags
, new_flags
))
701 dump_flag (&fh
.Flags
);
703 dump_flag (&new_flags
);
708 printf ("%d out of %d failed\n", errors
, count
);