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
},
112 { CONNECTEDFLAG
, N ("connected"), ALL_TYPES
}
115 static FlagBitsType pcb_flagbits
[] = {
116 { SHOWNUMBERFLAG
, N ("shownumber"), 1 },
117 { LOCALREFFLAG
, N ("localref"), 1 },
118 { CHECKPLANESFLAG
, N ("checkplanes"), 1 },
119 { SHOWDRCFLAG
, N ("showdrc"), 1 },
120 { RUBBERBANDFLAG
, N ("rubberband"), 1 },
121 { DESCRIPTIONFLAG
, N ("description"), 1 },
122 { NAMEONPCBFLAG
, N ("nameonpcb"), 1 },
123 { AUTODRCFLAG
, N ("autodrc"), 1 },
124 { ALLDIRECTIONFLAG
, N ("alldirection"), 1 },
125 { SWAPSTARTDIRFLAG
, N ("swapstartdir"), 1 },
126 { UNIQUENAMEFLAG
, N ("uniquename"), 1 },
127 { CLEARNEWFLAG
, N ("clearnew"), 1 },
128 { NEWFULLPOLYFLAG
, N ("newfullpoly"), 1 },
129 { SNAPPINFLAG
, N ("snappin"), 1 },
130 { SHOWMASKFLAG
, N ("showmask"), 1 },
131 { THINDRAWFLAG
, N ("thindraw"), 1 },
132 { ORTHOMOVEFLAG
, N ("orthomove"), 1 },
133 { LIVEROUTEFLAG
, N ("liveroute"), 1 },
134 { THINDRAWPOLYFLAG
, N ("thindrawpoly"), 1 },
135 { LOCKNAMESFLAG
, N ("locknames"), 1 },
136 { ONLYNAMESFLAG
, N ("onlynames"), 1 },
137 { HIDENAMESFLAG
, N ("hidenames"), 1 },
143 * This helper function maintains a small list of buffers which are
144 * used by flags_to_string(). Each buffer is allocated from the heap,
145 * but the caller must not free them (they get realloced when they're
146 * reused, but never completely freed).
154 static int bufptr
= 0;
158 #define B buffers[bufptr]
160 bufptr
= (bufptr
+ 1) % 10;
164 B
.ptr
= (char *) realloc (B
.ptr
, len
);
166 B
.ptr
= (char *) malloc (len
);
174 * This set of routines manages a list of layer-specific flags.
175 * Callers should call grow_layer_list(0) to reset the list, and
176 * set_layer_list(layer,1) to set bits in the layer list. The results
177 * are stored in layers[], which has num_layers valid entries.
180 static char *layers
= 0;
181 static int max_layers
= 0, num_layers
= 0;
184 grow_layer_list (int num
)
188 layers
= (char *) calloc (num
> 0 ? num
: 1, 1);
191 else if (num
> max_layers
)
194 layers
= (char *) realloc (layers
, max_layers
);
196 if (num
> num_layers
)
197 memset (layers
+ num_layers
, 0, num
- num_layers
- 1);
203 set_layer_list (int layer
, int v
)
205 if (layer
>= num_layers
)
206 grow_layer_list (layer
+ 1);
211 * These next two convert between layer lists and strings.
212 * parse_layer_list() is passed a pointer to a string, and parses a
213 * list of integer which reflect layers to be flagged. It returns a
214 * pointer to the first character following the list. The syntax of
215 * the list is a paren-surrounded, comma-separated list of integers
216 * and/or pairs of integers separated by a dash (like "(1,2,3-7)").
217 * Spaces and other punctuation are not allowed. The results are
218 * stored in layers[] defined above.
220 * print_layer_list() does the opposite - it uses the flags set in
221 * layers[] to build a string that represents them, using the syntax
226 /* Returns a pointer to the first character past the list. */
228 parse_layer_list (const char *bp
, int (*error
) (const char *))
230 const char *orig_bp
= bp
;
231 int l
= 0, range
= -1;
245 else if (*bp
== ')' || *bp
== ',' || *bp
== '-')
250 set_layer_list (range
++, value
);
259 else if (isdigit ((int) *bp
))
260 l
= l
* 10 + (*bp
- '0');
264 char *fmt
= "Syntax error parsing layer list \"%.*s\" at %c";
265 char *msg
= alloc_buf (strlen (fmt
) + strlen (orig_bp
));
266 sprintf (msg
, fmt
, bp
- orig_bp
+ 5, orig_bp
, *bp
);
279 /* Number of character the value "i" requires when printed. */
281 printed_int_length (int i
, int j
)
286 return 1 + (j
? 1 : 0);
288 return 2 + (j
? 1 : 0);
290 for (rv
= 1; i
>= 10; rv
++)
292 return rv
+ (j
? 1 : 0);
295 /* Returns a pointer to an internal buffer which is overwritten with
300 static char *buf
= 0;
301 static int buflen
= 0;
306 for (i
= 0; i
< num_layers
; i
++)
308 len
+= 1 + printed_int_length (i
, layers
[i
]);
312 buf
= (char *) realloc (buf
, len
);
314 buf
= (char *) malloc (len
);
321 for (i
= 0; i
< num_layers
; i
++)
326 for (j
= i
+ 1; j
< num_layers
&& layers
[j
] == 1; j
++)
330 sprintf (bp
, "%d-%d,", i
, j
- 1);
337 sprintf (bp
, "%d,", i
);
340 sprintf (bp
, "%d+,", i
);
343 sprintf (bp
, "%dS,", i
);
346 sprintf (bp
, "%dX,", i
);
350 sprintf (bp
, "%dt,", i
);
361 * Ok, now the two entry points to this file. The first, string_to_flags,
362 * is passed a string (usually from parse_y.y) and returns a "set of flags".
363 * In theory, this can be anything, but for now it's just an integer. Later
364 * it might be a structure, for example.
366 * Currently, there is no error handling :-P
370 error_ignore (const char *msg
)
374 static FlagType empty_flags
;
377 common_string_to_flags (const char *flagstring
,
378 int (*error
) (const char *msg
),
379 FlagBitsType
*flagbits
,
387 rv
.Flags
= empty_flags
;
390 error
= error_ignore
;
392 if (flagstring
== NULL
)
395 fp
= ep
= flagstring
;
400 while (*ep
&& *ep
!= '"')
404 for (ep
= fp
; *ep
&& *ep
!= ',' && *ep
!= '"' && *ep
!= '('; ep
++)
408 ep
= parse_layer_list (ep
+ 1, error
);
410 if (flen
== 7 && memcmp (fp
, "thermal", 7) == 0)
412 for (i
= 0; i
< MAX_LAYER
&& i
< num_layers
; i
++)
414 ASSIGN_THERM (i
, layers
[i
], &rv
);
418 for (i
= 0; i
< n_flagbits
; i
++)
419 if (flagbits
[i
].nlen
== flen
420 && memcmp (flagbits
[i
].name
, fp
, flen
) == 0)
423 SET_FLAG (flagbits
[i
].mask
, &rv
);
428 const char *fmt
= "Unknown flag: \"%.*s\" ignored";
429 char *msg
= alloc_buf (strlen (fmt
) + flen
);
430 sprintf (msg
, fmt
, flen
, fp
);
440 string_to_flags (const char *flagstring
,
441 int (*error
) (const char *msg
))
443 return common_string_to_flags (flagstring
,
446 ENTRIES (object_flagbits
));
450 string_to_pcbflags (const char *flagstring
,
451 int (*error
) (const char *msg
))
453 return common_string_to_flags (flagstring
,
456 ENTRIES (pcb_flagbits
));
461 * Given a set of flags for a given type of object, return a string
462 * which reflects those flags. The only requirement is that this
463 * string be parseable by string_to_flags.
465 * Note that this function knows a little about what kinds of flags
466 * will be automatically set by parsing, so it won't (for example)
467 * include the "via" flag for VIA_TYPEs because it knows those get
468 * forcibly set when vias are parsed.
472 common_flags_to_string (FlagType flags
,
474 FlagBitsType
*flagbits
,
479 FlagHolder fh
, savef
;
488 CLEAR_FLAG (VIAFLAG
, &fh
);
491 CLEAR_FLAG (RATFLAG
, &fh
);
494 CLEAR_FLAG (PINFLAG
, &fh
);
501 len
= 3; /* for "()\0" */
502 for (i
= 0; i
< n_flagbits
; i
++)
503 if ((flagbits
[i
].object_types
& object_type
)
504 && (TEST_FLAG (flagbits
[i
].mask
, &fh
)))
506 len
+= flagbits
[i
].nlen
+ 1;
507 CLEAR_FLAG (flagbits
[i
].mask
, &fh
);
510 if (TEST_ANY_THERMS (&fh
))
512 len
+= sizeof ("thermal()");
513 for (i
= 0; i
< MAX_LAYER
; i
++)
514 if (TEST_THERM (i
, &fh
))
515 len
+= printed_int_length (i
, GET_THERM (i
, &fh
)) + 1;
518 bp
= buf
= alloc_buf (len
+ 2);
523 for (i
= 0; i
< n_flagbits
; i
++)
524 if (flagbits
[i
].object_types
& object_type
525 && (TEST_FLAG (flagbits
[i
].mask
, &fh
)))
529 strcpy (bp
, flagbits
[i
].name
);
530 bp
+= flagbits
[i
].nlen
;
531 CLEAR_FLAG (flagbits
[i
].mask
, &fh
);
534 if (TEST_ANY_THERMS (&fh
))
538 strcpy (bp
, "thermal");
539 bp
+= strlen ("thermal");
541 for (i
= 0; i
< MAX_LAYER
; i
++)
542 if (TEST_THERM (i
, &fh
))
543 set_layer_list (i
, GET_THERM (i
, &fh
));
544 strcpy (bp
, print_layer_list ());
554 flags_to_string (FlagType flags
, int object_type
)
556 return common_flags_to_string (flags
,
559 ENTRIES (object_flagbits
));
563 pcbflags_to_string (FlagType flags
)
565 return common_flags_to_string (flags
,
568 ENTRIES (pcb_flagbits
));
574 dump_flag (FlagType
* f
)
577 printf ("F:%08x T:[", f
->f
);
578 for (l
= 0; l
< (MAX_LAYER
+ 7) / 8; l
++)
579 printf (" %02x", f
->t
[l
]);
585 mem_any_set (unsigned char *ptr
, int bytes
)
595 * This exists for standalone testing of this file.
597 * Compile as: gcc -DHAVE_CONFIG_H -DFLAG_TEST strflags.c -o strflags.x -I..
606 int errors
= 0, count
= 0;
609 srandom ((unsigned int) now
+ getpid ());
612 for (i
= 0; i
< 16; i
++)
616 if (i
!= 1 && i
!= 4 && i
!= 5 && i
!= 9)
617 set_layer_list (i
, 1);
619 set_layer_list (i
, 0);
620 p
= print_layer_list ();
621 printf ("%2d : %20s =", i
, p
);
622 parse_layer_list (p
+ 1, 0);
623 for (j
= 0; j
< num_layers
; j
++)
624 printf (" %d", layers
[j
]);
628 while (count
< 1000000)
637 fh
.Flags
= empty_flags
;
638 for (i
= 0; i
< ENTRIES (object_flagbits
); i
++)
640 if (TEST_FLAG (object_flagbits
[i
].mask
, &fh
))
642 if ((otype
& object_flagbits
[i
].object_types
) == 0)
644 if ((random () & 4) == 0)
647 otype
&= object_flagbits
[i
].object_types
;
648 SET_FLAG (object_flagbits
[i
].mask
, &fh
);
651 if (otype
& PIN_TYPES
)
652 for (i
= 0; i
< MAX_LAYER
; i
++)
654 ASSIGN_THERM (i
, 3, &fh
);
656 str
= flags_to_string (fh
.Flags
, otype
);
657 new_flags
= string_to_flags (str
, 0);
660 if (FLAGS_EQUAL (fh
.Flags
, new_flags
))
663 dump_flag (&fh
.Flags
);
665 dump_flag (&new_flags
);
671 while (count
< 1000000)
680 fh
.Flags
= empty_flags
;
681 for (i
= 0; i
< ENTRIES (pcb_flagbits
); i
++)
683 if (TEST_FLAG (pcb_flagbits
[i
].mask
, &fh
))
685 if ((random () & 4) == 0)
688 otype
&= pcb_flagbits
[i
].object_types
;
689 SET_FLAG (pcb_flagbits
[i
].mask
, &fh
);
692 str
= pcbflags_to_string (fh
.Flags
);
693 new_flags
= string_to_pcbflags (str
, 0);
696 if (FLAGS_EQUAL (fh
.Flags
, new_flags
))
699 dump_flag (&fh
.Flags
);
701 dump_flag (&new_flags
);
706 printf ("%d out of %d failed\n", errors
, count
);