2 * ************************** README *******************
4 * If the file format is modified in any way, update
5 * PCB_FILE_VERSION in file.h
7 * ************************** README *******************
14 * PCB, interactive printed circuit board design
15 * Copyright (C) 1994,1995,1996 Thomas Nau
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 * Contact addresses for paper mail and Email:
32 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
33 * Thomas.Nau@rz.uni-ulm.de
37 /* grammar to parse ASCII input of PCB description
58 #ifdef HAVE_LIBDMALLOC
59 # include <dmalloc.h> /* see http://dmalloc.com */
62 static LayerType
*Layer
;
63 static PolygonType
*Polygon
;
64 static SymbolType
*Symbol
;
66 static LibraryMenuType
*Menu
;
67 static bool LayerFlag
[MAX_LAYER
+ 2];
69 extern
char *yytext
; /* defined by LEX */
70 extern PCBType
*yyPCB
;
71 extern DataType
*yyData
;
72 extern ElementType
*yyElement
;
73 extern FontType
*yyFont
;
74 extern
int yylineno
; /* linenumber */
75 extern
char *yyfilename
; /* in this file */
77 static char *layer_group_string
;
79 static AttributeListType
*attr_list
;
81 int yyerror(const char *s
);
83 static int check_file_version
(int);
85 static void do_measure
(PLMeasure
*m
, Coord i
, double d
, int u
);
86 #define M(r,f,d) do_measure (&(r), f, d, 1)
88 /* Macros for interpreting what "measure" means - integer value only,
89 old units (mil), or new units (cmil). */
90 #define IV(m) integer_value (m)
91 #define OU(m) old_units (m)
92 #define NU(m) new_units (m)
94 static int integer_value
(PLMeasure m
);
95 static Coord old_units
(PLMeasure m
);
96 static Coord new_units
(PLMeasure m
);
99 #define YYERROR_VERBOSE 1
107 %
union /* define YYSTACK type */
116 %token
<number
> FLOATING
/* line thickness, coordinates ... */
117 %token
<integer
> INTEGER CHAR_CONST
/* flags ... */
118 %token
<string> STRING
/* element names ... */
120 %token T_FILEVERSION T_PCB T_LAYER T_VIA T_RAT T_LINE T_ARC T_RECTANGLE T_TEXT T_ELEMENTLINE
121 %token T_ELEMENT T_PIN T_PAD T_GRID T_FLAGS T_SYMBOL T_SYMBOLLINE T_CURSOR
122 %token T_ELEMENTARC T_MARK T_GROUPS T_STYLES T_POLYGON T_POLYGON_HOLE T_NETLIST T_NET T_CONN
123 %token T_AREA T_THERMAL T_DRC T_ATTRIBUTE
124 %token T_UMIL T_CMIL T_MIL T_IN T_NM T_UM T_MM T_M T_KM T_PX
125 %type
<integer
> symbolid
126 %type
<string> opt_string
127 %type
<flagtype
> flags
128 %type
<number
> number
129 %type
<measure
> measure
140 /* %start-doc pcbfile 00pcb
144 A special note about units: Older versions of @code{pcb} used mils
145 (1/1000 inch) as the base unit; a value of 500 in the file meant
146 half an inch. Newer versions uses a "high resolution" syntax,
147 where the base unit is 1/100 of a mil (0.000010 inch); a value of 500 in
148 the file means 5 mils. As a general rule, the variants of each entry
149 listed below which use square brackets are the high resolution formats
150 and use the 1/100 mil units, and the ones with parentheses are the older
151 variants and use 1 mil units. Note that when multiple variants
152 are listed, the most recent (and most preferred) format is the first
155 Symbolic and numeric flags (SFlags and NFlags) are described in
162 /* reset flags for 'used layers';
163 * init font and data pointers
169 Message
("illegal fileformat\n");
172 for
(i
= 0; i
< MAX_LAYER
+ 2; i
++)
173 LayerFlag
[i
] = false
;
174 yyFont
= &yyPCB
->Font
;
175 yyData
= yyPCB
->Data
;
178 layer_group_string
= NULL
;
194 PCBType
*pcb_save
= PCB
;
196 if
(layer_group_string
== NULL
)
197 layer_group_string
= Settings.Groups
;
198 CreateNewPCBPost
(yyPCB
, 0);
199 if
(ParseGroupString
(layer_group_string
, &yyPCB
->LayerGroups
, yyData
->LayerN
))
201 Message
("illegal layer-group string\n");
204 /* initialize the polygon clipping now since
205 * we didn't know the layer grouping before.
208 ALLPOLYGON_LOOP
(yyData
);
210 InitClip
(yyData
, layer
, polygon
);
216 |
{ PreLoadElementPCB
();
217 layer_group_string
= NULL
; }
219 { LayerFlag
[0] = true
;
222 PostLoadElementPCB
();
228 /* reset flags for 'used layers';
229 * init font and data pointers
233 if
(!yyData ||
!yyFont
)
235 Message
("illegal fileformat\n");
238 for
(i
= 0; i
< MAX_LAYER
+ 2; i
++)
239 LayerFlag
[i
] = false
;
253 /* mark all symbols invalid */
258 Message
("illegal fileformat\n");
261 yyFont
->Valid
= false
;
262 for
(i
= 0; i
<= MAX_FONTPOSITION
; i
++)
263 free
(yyFont
->Symbol
[i
].Line
);
264 bzero
(yyFont
->Symbol
, sizeof
(yyFont
->Symbol
));
268 yyFont
->Valid
= true
;
273 /* %start-doc pcbfile FileVersion
281 File format version. This version number represents the date when the pcb file
282 format was last changed.
285 Any version of pcb build from sources equal to or newer
286 than this number should be able to read the file. If this line is not present
287 in the input file then file format compatibility is not checked.
294 T_FILEVERSION
'[' INTEGER
']'
296 if
(check_file_version
($3) != 0)
303 /* %start-doc pcbfile PCB
306 PCB ["Name" Width Height]
307 PCB ("Name" Width Height]
313 Name of the PCB project
318 If you don't specify the size of the board, a very large default is
324 : T_PCB
'(' STRING
')'
327 yyPCB
->MaxWidth
= MAX_COORD
;
328 yyPCB
->MaxHeight
= MAX_COORD
;
330 | T_PCB
'(' STRING measure measure
')'
333 yyPCB
->MaxWidth
= OU
($4);
334 yyPCB
->MaxHeight
= OU
($5);
336 | T_PCB
'[' STRING measure measure
']'
339 yyPCB
->MaxWidth
= NU
($4);
340 yyPCB
->MaxHeight
= NU
($5);
344 /* %start-doc pcbfile Grid
347 Grid [Step OffsetX OffsetY Visible]
348 Grid (Step OffsetX OffsetY Visible)
349 Grid (Step OffsetX OffsetY)
354 Distance from one grid point to adjacent points. This value may be a
355 floating point number for the first two variants.
356 @item OffsetX OffsetY
357 The "origin" of the grid. Normally zero.
359 If non-zero, the grid will be visible on the screen.
370 : T_GRID
'(' measure measure measure
')'
372 yyPCB
->Grid
= OU
($3);
373 yyPCB
->GridOffsetX
= OU
($4);
374 yyPCB
->GridOffsetY
= OU
($5);
378 : T_GRID
'(' measure measure measure INTEGER
')'
380 yyPCB
->Grid
= OU
($3);
381 yyPCB
->GridOffsetX
= OU
($4);
382 yyPCB
->GridOffsetY
= OU
($5);
384 Settings.DrawGrid
= true
;
386 Settings.DrawGrid
= false
;
391 : T_GRID
'[' measure measure measure INTEGER
']'
393 yyPCB
->Grid
= NU
($3);
394 yyPCB
->GridOffsetX
= NU
($4);
395 yyPCB
->GridOffsetY
= NU
($5);
397 Settings.DrawGrid
= true
;
399 Settings.DrawGrid
= false
;
403 /* %start-doc pcbfile Cursor
412 Location of the cursor when the board was saved.
413 As of November 2012 the cursor position is not written to file anymore.
414 Older versions of pcb ignore the absence of this line in the pcb file.
416 The current zoom factor. Note that a zoom factor of "0" means 1 mil
417 per screen pixel, N means @math{2^N} mils per screen pixel, etc. The
418 first variant accepts floating point numbers. The special value
419 "1000" means "zoom to fit"
421 This field is ignored by PCB.
427 : T_CURSOR
'(' measure measure number
')'
429 yyPCB
->CursorX
= OU
($3);
430 yyPCB
->CursorY
= OU
($4);
432 | T_CURSOR
'[' measure measure number
']'
434 yyPCB
->CursorX
= NU
($3);
435 yyPCB
->CursorY
= NU
($4);
440 /* %start-doc pcbfile PolyArea
448 Minimum area of polygon island to retain. If a polygon has clearances that cause an isolated island to be created, then will only be retained if the area exceeds this minimum area.
455 | T_AREA
'[' number
']'
457 /* Read in cmil^2 for now; in future this should be a noop. */
458 yyPCB
->IsleArea
= MIL_TO_COORD
(MIL_TO_COORD
($3) / 100.0) / 100.0;
463 /* %start-doc pcbfile Thermal
471 Relative size of thermal fingers. A value of 1.0 makes the finger
472 width twice the clearance gap width (measured across the gap, not
473 diameter). The normal value is 0.5, which results in a finger width
474 the same as the clearance gap width.
482 | T_THERMAL
'[' number
']'
484 yyPCB
->ThermScale
= $3;
488 /* %start-doc pcbfile DRC
491 DRC [Bloat Shrink Line Silk Drill Ring]
492 DRC [Bloat Shrink Line Silk]
493 DRC [Bloat Shrink Line]
498 Minimum spacing between copper.
500 Minimum copper overlap to guarantee connectivity.
502 Minimum line thickness.
504 Minimum silk thickness.
508 Minimum width of the annular ring around pins and vias.
521 : T_DRC
'[' measure measure measure
']'
523 yyPCB
->Bloat
= NU
($3);
524 yyPCB
->Shrink
= NU
($4);
525 yyPCB
->minWid
= NU
($5);
526 yyPCB
->minRing
= NU
($5);
531 : T_DRC
'[' measure measure measure measure
']'
533 yyPCB
->Bloat
= NU
($3);
534 yyPCB
->Shrink
= NU
($4);
535 yyPCB
->minWid
= NU
($5);
536 yyPCB
->minSlk
= NU
($6);
537 yyPCB
->minRing
= NU
($5);
542 : T_DRC
'[' measure measure measure measure measure measure
']'
544 yyPCB
->Bloat
= NU
($3);
545 yyPCB
->Shrink
= NU
($4);
546 yyPCB
->minWid
= NU
($5);
547 yyPCB
->minSlk
= NU
($6);
548 yyPCB
->minDrill
= NU
($7);
549 yyPCB
->minRing
= NU
($8);
553 /* %start-doc pcbfile Flags
561 A number, whose value is normally given in hex, individual bits of which
562 represent pcb-wide flags as defined in @ref{PCBFlags}.
569 : T_FLAGS
'(' INTEGER
')'
571 yyPCB
->Flags
= MakeFlags
($3 & PCB_FLAGS
);
573 | T_FLAGS
'(' STRING
')'
575 yyPCB
->Flags
= string_to_pcbflags
($3, yyerror);
580 /* %start-doc pcbfile Groups
589 Encodes the layer grouping information. Each group is separated by a
590 colon, each member of each group is separated by a comma. Group
591 members are either numbers from @code{1}..@var{N} for each layer, and
592 the letters @code{c} or @code{s} representing the component side and
593 solder side of the board. Including @code{c} or @code{s} marks that
594 group as being the top or bottom side of the board.
597 Groups("1,2,c:3:4:5,6,s:7,8")
605 : T_GROUPS
'(' STRING
')'
607 layer_group_string
= $3;
612 /* %start-doc pcbfile Styles
621 Encodes the four routing styles @code{pcb} knows about. The four styles
622 are separated by colons. Each style consists of five parameters as follows:
626 The name of the style.
628 Width of lines and arcs.
630 Copper diameter of pins and vias.
632 Drill diameter of pins and vias.
634 Minimum spacing to other nets. If omitted, 10 mils is the default.
641 Styles("Signal,10,40,20:Power,25,60,35:Fat,40,60,35:Skinny,8,36,20")
642 Styles["Logic,1000,3600,2000,1000:Power,2500,6000,3500,1000:
643 @ @ @ Line,4000,6000,3500,1000:Breakout,600,2402,1181,600"]
647 Note that strings in actual files cannot span lines; the above example
648 is split across lines only to make it readable.
653 : T_STYLES
'(' STRING
')'
655 if
(ParseRouteString
($3, &yyPCB
->RouteStyle
[0], "mil"))
657 Message
("illegal route-style string\n");
661 | T_STYLES
'[' STRING
']'
663 if
(ParseRouteString
($3, &yyPCB
->RouteStyle
[0], "cmil"))
665 Message
("illegal route-style string\n");
679 | pcbdefinitions pcbdefinition
684 |
{ attr_list
= & yyPCB
->Attributes
; } attribute
689 /* clear pointer to force memory allocation by
690 * the appropriate subroutine
706 /* %start-doc pcbfile Via
709 Via [X Y Thickness Clearance Mask Drill "Name" SFlags]
710 Via (X Y Thickness Clearance Mask Drill "Name" NFlags)
711 Via (X Y Thickness Clearance Drill "Name" NFlags)
712 Via (X Y Thickness Drill "Name" NFlags)
713 Via (X Y Thickness "Name" NFlags)
718 coordinates of center
720 outer diameter of copper annulus
722 add to thickness to get clearance diameter
724 diameter of solder mask opening
728 string, name of via (vias have names?)
730 symbolic or numerical flags
738 /* x, y, thickness, clearance, mask, drilling-hole, name, flags */
739 : T_VIA
'[' measure measure measure measure measure measure STRING flags
']'
741 CreateNewVia
(yyData
, NU
($3), NU
($4), NU
($5), NU
($6), NU
($7),
748 /* x, y, thickness, clearance, mask, drilling-hole, name, flags */
749 : T_VIA
'(' measure measure measure measure measure measure STRING INTEGER
')'
751 CreateNewVia
(yyData
, OU
($3), OU
($4), OU
($5), OU
($6), OU
($7), OU
($8), $9,
759 /* x, y, thickness, clearance, drilling-hole, name, flags */
760 : T_VIA
'(' measure measure measure measure measure STRING INTEGER
')'
762 CreateNewVia
(yyData
, OU
($3), OU
($4), OU
($5), OU
($6),
763 OU
($5) + OU
($6), OU
($7), $8, OldFlags
($9));
769 /* x, y, thickness, drilling-hole, name, flags */
770 : T_VIA
'(' measure measure measure measure STRING INTEGER
')'
772 CreateNewVia
(yyData
, OU
($3), OU
($4), OU
($5), 2*GROUNDPLANEFRAME
,
773 OU
($5) + 2*MASKFRAME
, OU
($6), $7, OldFlags
($8));
779 /* old format: x, y, thickness, name, flags */
780 : T_VIA
'(' measure measure measure STRING INTEGER
')'
782 Coord hole
= (OU
($5) * DEFAULT_DRILLINGHOLE
);
784 /* make sure that there's enough copper left */
785 if
(OU
($5) - hole
< MIN_PINORVIACOPPER
&&
786 OU
($5) > MIN_PINORVIACOPPER
)
787 hole
= OU
($5) - MIN_PINORVIACOPPER
;
789 CreateNewVia
(yyData
, OU
($3), OU
($4), OU
($5), 2*GROUNDPLANEFRAME
,
790 OU
($5) + 2*MASKFRAME
, hole
, $6, OldFlags
($7));
795 /* %start-doc pcbfile Rat
798 Rat [X1 Y1 Group1 X2 Y2 Group2 SFlags]
799 Rat (X1 Y1 Group1 X2 Y2 Group2 NFlags)
804 The endpoints of the rat line.
806 The layer group each end is connected on.
808 Symbolic or numeric flags.
816 : T_RAT
'[' measure measure INTEGER measure measure INTEGER flags
']'
818 CreateNewRat
(yyData
, NU
($3), NU
($4), NU
($6), NU
($7), $5, $8,
819 Settings.RatThickness
, $9);
821 | T_RAT
'(' measure measure INTEGER measure measure INTEGER INTEGER
')'
823 CreateNewRat
(yyData
, OU
($3), OU
($4), OU
($6), OU
($7), $5, $8,
824 Settings.RatThickness
, OldFlags
($9));
828 /* %start-doc pcbfile Layer
831 Layer (LayerNum "Name") (
832 @ @ @ @dots{} contents @dots{}
838 The layer number. Layers are numbered sequentially, starting with 1.
839 The last two layers (9 and 10 by default) are solder-side silk and
840 component-side silk, in that order.
844 The contents of the layer, which may include attributes, lines, arcs, rectangles,
852 : T_LAYER
'(' INTEGER STRING opt_string
')' '('
854 if
($3 <= 0 ||
$3 > MAX_LAYER
+ 2)
856 yyerror("Layernumber out of range");
861 yyerror("Layernumber used twice");
864 Layer
= &yyData
->Layer
[$3-1];
866 /* memory for name is already allocated */
868 if
(Layer
->Name
== NULL
)
869 Layer
->Name
= strdup
("");
870 LayerFlag
[$3-1] = true
;
871 if
(yyData
->LayerN
+ 2 < $3)
872 yyData
->LayerN
= $3 - 2;
884 | layerdefinitions layerdefinition
894 /* x1, y1, x2, y2, flags */
895 | T_RECTANGLE
'(' measure measure measure measure INTEGER
')'
897 CreateNewPolygonFromRectangle
(Layer
,
898 OU
($3), OU
($4), OU
($3) + OU
($5), OU
($4) + OU
($6), OldFlags
($7));
903 |
{ attr_list
= & Layer
->Attributes
; } attribute
906 /* %start-doc pcbfile Line
909 Line [X1 Y1 X2 Y2 Thickness Clearance SFlags]
910 Line (X1 Y1 X2 Y2 Thickness Clearance NFlags)
911 Line (X1 Y1 X2 Y2 Thickness NFlags)
916 The end points of the line
918 The width of the line
920 The amount of space cleared around the line when the line passes
921 through a polygon. The clearance is added to the thickness to get the
922 thickness of the clear; thus the space between the line and the
923 polygon is @math{Clearance/2} wide.
925 Symbolic or numeric flags
933 /* x1, y1, x2, y2, thickness, clearance, flags */
934 : T_LINE
'[' measure measure measure measure measure measure flags
']'
936 CreateNewLineOnLayer
(Layer
, NU
($3), NU
($4), NU
($5), NU
($6),
937 NU
($7), NU
($8), $9);
942 /* x1, y1, x2, y2, thickness, clearance, flags */
943 : T_LINE
'(' measure measure measure measure measure measure INTEGER
')'
945 CreateNewLineOnLayer
(Layer
, OU
($3), OU
($4), OU
($5), OU
($6),
946 OU
($7), OU
($8), OldFlags
($9));
951 /* x1, y1, x2, y2, thickness, flags */
952 : T_LINE
'(' measure measure measure measure measure measure
')'
954 /* eliminate old-style rat-lines */
955 if
((IV
($8) & RATFLAG
) == 0)
956 CreateNewLineOnLayer
(Layer
, OU
($3), OU
($4), OU
($5), OU
($6), OU
($7),
957 200*GROUNDPLANEFRAME
, OldFlags
(IV
($8)));
961 /* %start-doc pcbfile Arc
964 Arc [X Y Width Height Thickness Clearance StartAngle DeltaAngle SFlags]
965 Arc (X Y Width Height Thickness Clearance StartAngle DeltaAngle NFlags)
966 Arc (X Y Width Height Thickness StartAngle DeltaAngle NFlags)
971 Coordinates of the center of the arc.
973 The width and height, from the center to the edge. The bounds of the
974 circle of which this arc is a segment, is thus @math{2*Width} by
977 The width of the copper trace which forms the arc.
979 The amount of space cleared around the arc when the line passes
980 through a polygon. The clearance is added to the thickness to get the
981 thickness of the clear; thus the space between the arc and the polygon
982 is @math{Clearance/2} wide.
984 The angle of one end of the arc, in degrees. In PCB, an angle of zero
985 points left (negative X direction), and 90 degrees points down
986 (positive Y direction).
988 The sweep of the arc. This may be negative. Positive angles sweep
991 Symbolic or numeric flags.
999 /* x, y, width, height, thickness, clearance, startangle, delta, flags */
1000 : T_ARC
'[' measure measure measure measure measure measure number number flags
']'
1002 CreateNewArcOnLayer
(Layer
, NU
($3), NU
($4), NU
($5), NU
($6), $9, $10,
1003 NU
($7), NU
($8), $11);
1008 /* x, y, width, height, thickness, clearance, startangle, delta, flags */
1009 : T_ARC
'(' measure measure measure measure measure measure number number INTEGER
')'
1011 CreateNewArcOnLayer
(Layer
, OU
($3), OU
($4), OU
($5), OU
($6), $9, $10,
1012 OU
($7), OU
($8), OldFlags
($11));
1017 /* x, y, width, height, thickness, startangle, delta, flags */
1018 : T_ARC
'(' measure measure measure measure measure measure number INTEGER
')'
1020 CreateNewArcOnLayer
(Layer
, OU
($3), OU
($4), OU
($5), OU
($5), IV
($8), $9,
1021 OU
($7), 200*GROUNDPLANEFRAME
, OldFlags
($10));
1025 /* %start-doc pcbfile Text
1028 Text [X Y Direction Scale "String" SFlags]
1029 Text (X Y Direction Scale "String" NFlags)
1030 Text (X Y Direction "String" NFlags)
1035 The location of the upper left corner of the text.
1037 0 means text is drawn left to right, 1 means up, 2 means right to left
1038 (i.e. upside down), and 3 means down.
1040 Size of the text, as a percentage of the ``default'' size of of the
1041 font (the default font is about 40 mils high). Default is 100 (40
1046 Symbolic or numeric flags.
1054 /* x, y, direction, text, flags */
1055 : T_TEXT
'(' measure measure number STRING INTEGER
')'
1057 /* use a default scale of 100% */
1058 CreateNewText
(Layer
,yyFont
,OU
($3), OU
($4), $5, 100, $6, OldFlags
($7));
1064 /* x, y, direction, scale, text, flags */
1065 : T_TEXT
'(' measure measure number number STRING INTEGER
')'
1067 if
($8 & ONSILKFLAG
)
1069 LayerType
*lay
= &yyData
->Layer
[yyData
->LayerN
+
1070 (($8 & ONSOLDERFLAG
) ? SOLDER_LAYER
: COMPONENT_LAYER
)];
1072 CreateNewText
(lay
,yyFont
, OU
($3), OU
($4), $5, $6, $7,
1076 CreateNewText
(Layer
, yyFont
, OU
($3), OU
($4), $5, $6, $7,
1082 /* x, y, direction, scale, text, flags */
1083 : T_TEXT
'[' measure measure number number STRING flags
']'
1085 /* FIXME: shouldn't know about .f */
1086 /* I don't think this matters because anything with hi_format
1087 * will have the silk on its own layer in the file rather
1088 * than using the ONSILKFLAG and having it in a copper layer.
1089 * Thus there is no need for anything besides the 'else'
1090 * part of this code.
1092 if
($8.f
& ONSILKFLAG
)
1094 LayerType
*lay
= &yyData
->Layer
[yyData
->LayerN
+
1095 (($8.f
& ONSOLDERFLAG
) ? SOLDER_LAYER
: COMPONENT_LAYER
)];
1097 CreateNewText
(lay
, yyFont
, NU
($3), NU
($4), $5, $6, $7, $8);
1100 CreateNewText
(Layer
, yyFont
, NU
($3), NU
($4), $5, $6, $7, $8);
1105 /* %start-doc pcbfile Polygon
1109 @ @ @ @dots{} (X Y) @dots{}
1110 @ @ @ @dots{} [X Y] @dots{}
1112 @ @ @ @ @ @ @dots{} (X Y) @dots{}
1113 @ @ @ @ @ @ @dots{} [X Y] @dots{}
1121 Symbolic or numeric flags.
1123 Coordinates of each vertex. You must list at least three coordinates.
1125 Defines a hole within the polygon's outer contour. There may be zero or more such sections.
1131 : /* flags are passed in */
1132 T_POLYGON
'(' flags
')' '('
1134 Polygon
= CreateNewPolygon
(Layer
, $3);
1139 Cardinal contour
, contour_start
, contour_end
;
1140 bool bad_contour_found
= false
;
1142 for
(contour
= 0; contour
<= Polygon
->HoleIndexN
; contour
++)
1144 contour_start
= (contour
== 0) ?
1145 0 : Polygon
->HoleIndex
[contour
- 1];
1146 contour_end
= (contour
== Polygon
->HoleIndexN
) ?
1148 Polygon
->HoleIndex
[contour
];
1149 if
(contour_end
- contour_start
< 3)
1150 bad_contour_found
= true
;
1153 if
(bad_contour_found
)
1155 Message
("WARNING parsing file '%s'\n"
1157 " description: 'ignored polygon (< 3 points in a contour)'\n",
1158 yyfilename
, yylineno
);
1159 DestroyObject
(yyData
, POLYGON_TYPE
, Layer
, Polygon
, Polygon
);
1163 SetPolygonBoundingBox
(Polygon
);
1164 if
(!Layer
->polygon_tree
)
1165 Layer
->polygon_tree
= r_create_tree
(NULL
, 0, 0);
1166 r_insert_entry
(Layer
->polygon_tree
, (BoxType
*) Polygon
, 0);
1173 | polygonholes polygonhole
1177 : T_POLYGON_HOLE
'('
1179 CreateNewHoleInPolygon
(Polygon
);
1186 | polygonpoint polygonpoints
1191 : '(' measure measure
')'
1193 CreateNewPointInPolygon
(Polygon
, OU
($2), OU
($3));
1195 |
'[' measure measure
']'
1197 CreateNewPointInPolygon
(Polygon
, NU
($2), NU
($3));
1201 /* %start-doc pcbfile Element
1204 Element [SFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TSFlags] (
1205 Element (NFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TNFlags) (
1206 Element (NFlags "Desc" "Name" "Value" TX TY TDir TScale TNFlags) (
1207 Element (NFlags "Desc" "Name" TX TY TDir TScale TNFlags) (
1208 Element ("Desc" "Name" TX TY TDir TScale TNFlags) (
1209 @ @ @ @dots{} contents @dots{}
1215 Symbolic or numeric flags, for the element as a whole.
1217 Numeric flags, for the element as a whole.
1219 The description of the element. This is one of the three strings
1220 which can be displayed on the screen.
1222 The name of the element, usually the reference designator.
1224 The value of the element.
1226 The location of the element's mark. This is the reference point
1227 for placing the element and its pins and pads.
1229 The upper left corner of the text (one of the three strings).
1231 The relative direction of the text. 0 means left to right for
1232 an unrotated element, 1 means up, 2 left, 3 down.
1234 Size of the text, as a percentage of the ``default'' size of of the
1235 font (the default font is about 40 mils high). Default is 100 (40
1238 Symbolic or numeric flags, for the text.
1240 Numeric flags, for the text.
1243 Elements may contain pins, pads, element lines, element arcs,
1244 attributes, and (for older elements) an optional mark. Note that
1245 element definitions that have the mark coordinates in the element
1246 line, only support pins and pads which use relative coordinates. The
1247 pin and pad coordinates are relative to the mark. Element definitions
1248 which do not include the mark coordinates in the element line, may
1249 have a Mark definition in their contents, and only use pin and pad
1250 definitions which use absolute coordinates.
1256 | element_1.3
.4_format
1258 | element_1.7_format
1263 /* element_flags, description, pcb-name,
1264 * text_x, text_y, text_direction, text_scale, text_flags
1266 : T_ELEMENT
'(' STRING STRING measure measure INTEGER
')' '('
1268 yyElement
= CreateNewElement
(yyData
, yyElement
, yyFont
, NoFlags
(),
1269 $3, $4, NULL
, OU
($5), OU
($6), $7, 100, NoFlags
(), false
);
1274 elementdefinitions
')'
1276 SetElementBoundingBox
(yyData
, yyElement
, yyFont
);
1280 element_1.3
.4_format
1281 /* element_flags, description, pcb-name,
1282 * text_x, text_y, text_direction, text_scale, text_flags
1284 : T_ELEMENT
'(' INTEGER STRING STRING measure measure measure measure INTEGER
')' '('
1286 yyElement
= CreateNewElement
(yyData
, yyElement
, yyFont
, OldFlags
($3),
1287 $4, $5, NULL
, OU
($6), OU
($7), IV
($8), IV
($9), OldFlags
($10), false
);
1292 elementdefinitions
')'
1294 SetElementBoundingBox
(yyData
, yyElement
, yyFont
);
1299 /* element_flags, description, pcb-name, value,
1300 * text_x, text_y, text_direction, text_scale, text_flags
1302 : T_ELEMENT
'(' INTEGER STRING STRING STRING measure measure measure measure INTEGER
')' '('
1304 yyElement
= CreateNewElement
(yyData
, yyElement
, yyFont
, OldFlags
($3),
1305 $4, $5, $6, OU
($7), OU
($8), IV
($9), IV
($10), OldFlags
($11), false
);
1311 elementdefinitions
')'
1313 SetElementBoundingBox
(yyData
, yyElement
, yyFont
);
1318 /* element_flags, description, pcb-name, value, mark_x, mark_y,
1319 * text_x, text_y, text_direction, text_scale, text_flags
1321 : T_ELEMENT
'(' INTEGER STRING STRING STRING measure measure
1322 measure measure number number INTEGER
')' '('
1324 yyElement
= CreateNewElement
(yyData
, yyElement
, yyFont
, OldFlags
($3),
1325 $4, $5, $6, OU
($7) + OU
($9), OU
($8) + OU
($10),
1326 $11, $12, OldFlags
($13), false
);
1327 yyElement
->MarkX
= OU
($7);
1328 yyElement
->MarkY
= OU
($8);
1335 SetElementBoundingBox
(yyData
, yyElement
, yyFont
);
1340 /* element_flags, description, pcb-name, value, mark_x, mark_y,
1341 * text_x, text_y, text_direction, text_scale, text_flags
1343 : T_ELEMENT
'[' flags STRING STRING STRING measure measure
1344 measure measure number number flags
']' '('
1346 yyElement
= CreateNewElement
(yyData
, yyElement
, yyFont
, $3,
1347 $4, $5, $6, NU
($7) + NU
($9), NU
($8) + NU
($10),
1348 $11, $12, $13, false
);
1349 yyElement
->MarkX
= NU
($7);
1350 yyElement
->MarkY
= NU
($8);
1357 SetElementBoundingBox
(yyData
, yyElement
, yyFont
);
1361 /* %start-doc pcbfile ElementLine
1364 ElementLine [X1 Y1 X2 Y2 Thickness]
1365 ElementLine (X1 Y1 X2 Y2 Thickness)
1370 Coordinates of the endpoints of the line. These are relative to the
1371 Element's mark point for new element formats, or absolute for older
1374 The width of the silk for this line.
1379 /* %start-doc pcbfile ElementArc
1382 ElementArc [X Y Width Height StartAngle DeltaAngle Thickness]
1383 ElementArc (X Y Width Height StartAngle DeltaAngle Thickness)
1388 Coordinates of the center of the arc. These are relative to the
1389 Element's mark point for new element formats, or absolute for older
1392 The width and height, from the center to the edge. The bounds of the
1393 circle of which this arc is a segment, is thus @math{2*Width} by
1396 The angle of one end of the arc, in degrees. In PCB, an angle of zero
1397 points left (negative X direction), and 90 degrees points down
1398 (positive Y direction).
1400 The sweep of the arc. This may be negative. Positive angles sweep
1403 The width of the silk line which forms the arc.
1408 /* %start-doc pcbfile Mark
1417 Coordinates of the Mark, for older element formats that don't have
1418 the mark as part of the Element line.
1425 | elementdefinitions elementdefinition
1434 /* x1, y1, x2, y2, thickness */
1435 | T_ELEMENTLINE
'[' measure measure measure measure measure
']'
1437 CreateNewLineInElement
(yyElement
, NU
($3), NU
($4), NU
($5), NU
($6), NU
($7));
1439 /* x1, y1, x2, y2, thickness */
1440 | T_ELEMENTLINE
'(' measure measure measure measure measure
')'
1442 CreateNewLineInElement
(yyElement
, OU
($3), OU
($4), OU
($5), OU
($6), OU
($7));
1444 /* x, y, width, height, startangle, anglediff, thickness */
1445 | T_ELEMENTARC
'[' measure measure measure measure number number measure
']'
1447 CreateNewArcInElement
(yyElement
, NU
($3), NU
($4), NU
($5), NU
($6), $7, $8, NU
($9));
1449 /* x, y, width, height, startangle, anglediff, thickness */
1450 | T_ELEMENTARC
'(' measure measure measure measure number number measure
')'
1452 CreateNewArcInElement
(yyElement
, OU
($3), OU
($4), OU
($5), OU
($6), $7, $8, OU
($9));
1455 | T_MARK
'[' measure measure
']'
1457 yyElement
->MarkX
= NU
($3);
1458 yyElement
->MarkY
= NU
($4);
1460 | T_MARK
'(' measure measure
')'
1462 yyElement
->MarkX
= OU
($3);
1463 yyElement
->MarkY
= OU
($4);
1465 |
{ attr_list
= & yyElement
->Attributes
; } attribute
1470 | relementdefs relementdef
1478 /* x1, y1, x2, y2, thickness */
1479 | T_ELEMENTLINE
'[' measure measure measure measure measure
']'
1481 CreateNewLineInElement
(yyElement
, NU
($3) + yyElement
->MarkX
,
1482 NU
($4) + yyElement
->MarkY
, NU
($5) + yyElement
->MarkX
,
1483 NU
($6) + yyElement
->MarkY
, NU
($7));
1485 | T_ELEMENTLINE
'(' measure measure measure measure measure
')'
1487 CreateNewLineInElement
(yyElement
, OU
($3) + yyElement
->MarkX
,
1488 OU
($4) + yyElement
->MarkY
, OU
($5) + yyElement
->MarkX
,
1489 OU
($6) + yyElement
->MarkY
, OU
($7));
1491 /* x, y, width, height, startangle, anglediff, thickness */
1492 | T_ELEMENTARC
'[' measure measure measure measure number number measure
']'
1494 CreateNewArcInElement
(yyElement
, NU
($3) + yyElement
->MarkX
,
1495 NU
($4) + yyElement
->MarkY
, NU
($5), NU
($6), $7, $8, NU
($9));
1497 | T_ELEMENTARC
'(' measure measure measure measure number number measure
')'
1499 CreateNewArcInElement
(yyElement
, OU
($3) + yyElement
->MarkX
,
1500 OU
($4) + yyElement
->MarkY
, OU
($5), OU
($6), $7, $8, OU
($9));
1502 |
{ attr_list
= & yyElement
->Attributes
; } attribute
1505 /* %start-doc pcbfile Pin
1508 Pin [rX rY Thickness Clearance Mask Drill "Name" "Number" SFlags]
1509 Pin (rX rY Thickness Clearance Mask Drill "Name" "Number" NFlags)
1510 Pin (aX aY Thickness Drill "Name" "Number" NFlags)
1511 Pin (aX aY Thickness Drill "Name" NFlags)
1512 Pin (aX aY Thickness "Name" NFlags)
1517 coordinates of center, relative to the element's mark
1519 absolute coordinates of center.
1521 outer diameter of copper annulus
1523 add to thickness to get clearance diameter
1525 diameter of solder mask opening
1533 symbolic or numerical flags
1535 numerical flags only
1541 /* x, y, thickness, clearance, mask, drilling hole, name,
1543 : T_PIN
'[' measure measure measure measure measure measure STRING STRING flags
']'
1545 CreateNewPin
(yyElement
, NU
($3) + yyElement
->MarkX
,
1546 NU
($4) + yyElement
->MarkY
, NU
($5), NU
($6), NU
($7), NU
($8), $9,
1553 /* x, y, thickness, clearance, mask, drilling hole, name,
1555 : T_PIN
'(' measure measure measure measure measure measure STRING STRING INTEGER
')'
1557 CreateNewPin
(yyElement
, OU
($3) + yyElement
->MarkX
,
1558 OU
($4) + yyElement
->MarkY
, OU
($5), OU
($6), OU
($7), OU
($8), $9,
1559 $10, OldFlags
($11));
1566 /* x, y, thickness, drilling hole, name, number, flags */
1567 : T_PIN
'(' measure measure measure measure STRING STRING INTEGER
')'
1569 CreateNewPin
(yyElement
, OU
($3), OU
($4), OU
($5), 2*GROUNDPLANEFRAME
,
1570 OU
($5) + 2*MASKFRAME
, OU
($6), $7, $8, OldFlags
($9));
1577 /* x, y, thickness, drilling hole, name, flags */
1578 : T_PIN
'(' measure measure measure measure STRING INTEGER
')'
1582 sprintf
(p_number
, "%d", pin_num
++);
1583 CreateNewPin
(yyElement
, OU
($3), OU
($4), OU
($5), 2*GROUNDPLANEFRAME
,
1584 OU
($5) + 2*MASKFRAME
, OU
($6), $7, p_number
, OldFlags
($8));
1591 /* old format: x, y, thickness, name, flags
1592 * drilling hole is 40% of the diameter
1594 : T_PIN
'(' measure measure measure STRING INTEGER
')'
1596 Coord hole
= OU
($5) * DEFAULT_DRILLINGHOLE
;
1599 /* make sure that there's enough copper left */
1600 if
(OU
($5) - hole
< MIN_PINORVIACOPPER
&&
1601 OU
($5) > MIN_PINORVIACOPPER
)
1602 hole
= OU
($5) - MIN_PINORVIACOPPER
;
1604 sprintf
(p_number
, "%d", pin_num
++);
1605 CreateNewPin
(yyElement
, OU
($3), OU
($4), OU
($5), 2*GROUNDPLANEFRAME
,
1606 OU
($5) + 2*MASKFRAME
, hole
, $6, p_number
, OldFlags
($7));
1611 /* %start-doc pcbfile Pad
1614 Pad [rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" SFlags]
1615 Pad (rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" NFlags)
1616 Pad (aX1 aY1 aX2 aY2 Thickness "Name" "Number" NFlags)
1617 Pad (aX1 aY1 aX2 aY2 Thickness "Name" NFlags)
1621 @item rX1 rY1 rX2 rY2
1622 Coordinates of the endpoints of the pad, relative to the element's
1623 mark. Note that the copper extends beyond these coordinates by half
1624 the thickness. To make a square or round pad, specify the same
1626 @item aX1 aY1 aX2 aY2
1627 Same, but absolute coordinates of the endpoints of the pad.
1631 add to thickness to get clearance width.
1633 width of solder mask opening.
1639 symbolic or numerical flags
1641 numerical flags only
1647 /* x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags */
1648 : T_PAD
'[' measure measure measure measure measure measure measure STRING STRING flags
']'
1650 CreateNewPad
(yyElement
, NU
($3) + yyElement
->MarkX
,
1651 NU
($4) + yyElement
->MarkY
,
1652 NU
($5) + yyElement
->MarkX
,
1653 NU
($6) + yyElement
->MarkY
, NU
($7), NU
($8), NU
($9),
1661 /* x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags */
1662 : T_PAD
'(' measure measure measure measure measure measure measure STRING STRING INTEGER
')'
1664 CreateNewPad
(yyElement
,OU
($3) + yyElement
->MarkX
,
1665 OU
($4) + yyElement
->MarkY
, OU
($5) + yyElement
->MarkX
,
1666 OU
($6) + yyElement
->MarkY
, OU
($7), OU
($8), OU
($9),
1667 $10, $11, OldFlags
($12));
1674 /* x1, y1, x2, y2, thickness, name , pad number, flags */
1675 : T_PAD
'(' measure measure measure measure measure STRING STRING INTEGER
')'
1677 CreateNewPad
(yyElement
,OU
($3),OU
($4),OU
($5),OU
($6),OU
($7), 2*GROUNDPLANEFRAME
,
1678 OU
($7) + 2*MASKFRAME
, $8, $9, OldFlags
($10));
1685 /* x1, y1, x2, y2, thickness, name and flags */
1686 : T_PAD
'(' measure measure measure measure measure STRING INTEGER
')'
1690 sprintf
(p_number
, "%d", pin_num
++);
1691 CreateNewPad
(yyElement
,OU
($3),OU
($4),OU
($5),OU
($6),OU
($7), 2*GROUNDPLANEFRAME
,
1692 OU
($7) + 2*MASKFRAME
, $8,p_number
, OldFlags
($9));
1697 flags
: INTEGER
{ $$
= OldFlags
($1); }
1698 | STRING
{ $$
= string_to_flags
($1, yyerror); }
1706 /* %start-doc pcbfile Symbol
1709 Symbol [Char Delta] (
1710 Symbol (Char Delta) (
1711 @ @ @ @dots{} symbol lines @dots{}
1717 The character or numerical character value this symbol represents.
1718 Characters must be in single quotes.
1720 Additional space to allow after this character.
1725 symbol
: symbolhead symboldata
')'
1727 symbolhead
: T_SYMBOL
'[' symbolid measure
']' '('
1729 if
($3 <= 0 ||
$3 > MAX_FONTPOSITION
)
1731 yyerror("fontposition out of range");
1734 Symbol
= &yyFont
->Symbol
[$3];
1737 yyerror("symbol ID used twice");
1740 Symbol
->Valid
= true
;
1741 Symbol
->Delta
= NU
($4);
1743 | T_SYMBOL
'(' symbolid measure
')' '('
1745 if
($3 <= 0 ||
$3 > MAX_FONTPOSITION
)
1747 yyerror("fontposition out of range");
1750 Symbol
= &yyFont
->Symbol
[$3];
1753 yyerror("symbol ID used twice");
1756 Symbol
->Valid
= true
;
1757 Symbol
->Delta
= OU
($4);
1768 | symboldata symboldefinition
1769 | symboldata hiressymbol
1772 /* %start-doc pcbfile SymbolLine
1775 SymbolLine [X1 Y1 X2 Y2 Thickness]
1776 SymbolLine (X1 Y1 X2 Y2 Thickness)
1781 The endpoints of this line.
1783 The width of this line.
1789 /* x1, y1, x2, y2, thickness */
1790 : T_SYMBOLLINE
'(' measure measure measure measure measure
')'
1792 CreateNewLineInSymbol
(Symbol
, OU
($3), OU
($4), OU
($5), OU
($6), OU
($7));
1796 /* x1, y1, x2, y2, thickness */
1797 : T_SYMBOLLINE
'[' measure measure measure measure measure
']'
1799 CreateNewLineInSymbol
(Symbol
, NU
($3), NU
($4), NU
($5), NU
($6), NU
($7));
1803 /* %start-doc pcbfile Netlist
1807 @ @ @ @dots{} nets @dots{}
1813 pcbnetlist
: pcbnetdef
1817 /* net(...) net(...) ... */
1818 : T_NETLIST
'(' ')' '('
1832 /* %start-doc pcbfile Net
1835 Net ("Name" "Style") (
1836 @ @ @ @dots{} connects @dots{}
1842 The name of this net.
1844 The routing style that should be used when autorouting this net.
1850 /* name style pin pin ... */
1851 : T_NET
'(' STRING STRING
')' '('
1853 Menu
= CreateNewNet
(&yyPCB
->NetlistLib
, $3, $4);
1870 /* %start-doc pcbfile Connect
1878 The name of a pin or pad which is included in this net. Pin and Pad
1879 names are named by the refdes and pin name, like @code{"U14-7"} for
1880 pin 7 of U14, or @code{"T4-E"} for pin E of T4.
1886 : T_CONN
'(' STRING
')'
1888 CreateNewConnection
(Menu
, $3);
1893 /* %start-doc pcbfile Attribute
1896 Attribute ("Name" "Value")
1899 Attributes allow boards and elements to have arbitrary data attached
1900 to them, which is not directly used by PCB itself but may be of use by
1901 other programs or users.
1905 The name of the attribute
1908 The value of the attribute. Values are always stored as strings, even
1909 if the value is interpreted as, for example, a number.
1916 : T_ATTRIBUTE
'(' STRING STRING
')'
1918 CreateNewAttribute
(attr_list
, $3, $4 ?
$4 : (char *)"");
1924 opt_string
: STRING
{ $$
= $1; }
1925 |
/* empty */ { $$
= 0; }
1929 : FLOATING
{ $$
= $1; }
1930 | INTEGER
{ $$
= $1; }
1934 /* Default unit (no suffix) is cmil */
1935 : number
{ do_measure
(&$$
, $1, MIL_TO_COORD
($1) / 100.0, 0); }
1936 | number T_UMIL
{ M
($$
, $1, MIL_TO_COORD
($1) / 100000.0); }
1937 | number T_CMIL
{ M
($$
, $1, MIL_TO_COORD
($1) / 100.0); }
1938 | number T_MIL
{ M
($$
, $1, MIL_TO_COORD
($1)); }
1939 | number T_IN
{ M
($$
, $1, INCH_TO_COORD
($1)); }
1940 | number T_NM
{ M
($$
, $1, MM_TO_COORD
($1) / 1000000.0); }
1941 | number T_PX
{ M
($$
, $1, MM_TO_COORD
($1) / 1000000.0); }
1942 | number T_UM
{ M
($$
, $1, MM_TO_COORD
($1) / 1000.0); }
1943 | number T_MM
{ M
($$
, $1, MM_TO_COORD
($1)); }
1944 | number T_M
{ M
($$
, $1, MM_TO_COORD
($1) * 1000.0); }
1945 | number T_KM
{ M
($$
, $1, MM_TO_COORD
($1) * 1000000.0); }
1950 /* ---------------------------------------------------------------------------
1951 * error routine called by parser library
1953 int yyerror(const char * s
)
1955 Message
("ERROR parsing file '%s'\n"
1957 " description: '%s'\n",
1958 yyfilename
, yylineno
, s
);
1968 check_file_version
(int ver
)
1970 if
( ver
> PCB_FILE_VERSION
) {
1971 Message
("ERROR: The file you are attempting to load is in a format\n"
1972 "which is too new for this version of pcb. To load this file\n"
1973 "you need a version of pcb which is >= %d. If you are\n"
1974 "using a version built from git source, the source date\n"
1975 "must be >= %d. This copy of pcb can only read files\n"
1976 "up to file version %d.\n", ver
, ver
, PCB_FILE_VERSION
);
1984 do_measure
(PLMeasure
*m
, Coord i
, double d
, int u
)
1987 m
->bval
= round
(d
);
1993 integer_value
(PLMeasure m
)
1996 yyerror("units ignored here");
2001 old_units
(PLMeasure m
)
2005 return round
(MIL_TO_COORD
(m.ival
));
2009 new_units
(PLMeasure m
)
2013 return round
(MIL_TO_COORD
(m.ival
) / 100.0);