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
59 #ifdef HAVE_LIBDMALLOC
60 # include <dmalloc.h> /* see http://dmalloc.com */
63 static LayerType
*Layer
;
64 static PolygonType
*Polygon
;
65 static SymbolType
*Symbol
;
67 static LibraryMenuType
*Menu
;
68 static bool LayerFlag
[MAX_LAYER
+ 2];
70 extern
char *yytext
; /* defined by LEX */
71 extern PCBType
*yyPCB
;
72 extern DataType
*yyData
;
73 extern ElementType
*yyElement
;
74 extern FontType
*yyFont
;
75 extern
int yylineno
; /* linenumber */
76 extern
char *yyfilename
; /* in this file */
78 static AttributeListType
*attr_list
;
80 int yyerror(const char *s
);
82 static int check_file_version
(int);
84 static void do_measure
(PLMeasure
*m
, Coord i
, double d
, int u
);
85 #define M(r,f,d) do_measure (&(r), f, d, 1)
87 /* Macros for interpreting what "measure" means - integer value only,
88 old units (mil), or new units (cmil). */
89 #define IV(m) integer_value (m)
90 #define OU(m) old_units (m)
91 #define NU(m) new_units (m)
93 static int integer_value
(PLMeasure m
);
94 static Coord old_units
(PLMeasure m
);
95 static Coord new_units
(PLMeasure m
);
98 #define YYERROR_VERBOSE 1
106 %
union /* define YYSTACK type */
115 %token
<number
> FLOATING
/* line thickness, coordinates ... */
116 %token
<integer
> INTEGER CHAR_CONST
/* flags ... */
117 %token
<string> STRING
/* element names ... */
119 %token T_FILEVERSION T_PCB T_LAYER T_VIA T_RAT T_LINE T_ARC T_RECTANGLE T_TEXT T_ELEMENTLINE
120 %token T_ELEMENT T_PIN T_PAD T_GRID T_FLAGS T_SYMBOL T_SYMBOLLINE T_CURSOR
121 %token T_ELEMENTARC T_MARK T_GROUPS T_STYLES T_POLYGON T_POLYGON_HOLE T_NETLIST T_NET T_CONN
122 %token T_AREA T_THERMAL T_DRC T_ATTRIBUTE
123 %token T_UMIL T_CMIL T_MIL T_IN T_NM T_UM T_MM T_M T_KM T_PX
124 %type
<integer
> symbolid
125 %type
<string> opt_string
126 %type
<flagtype
> flags
127 %type
<number
> number
128 %type
<measure
> measure
139 /* %start-doc pcbfile 00pcb
143 A special note about units: Older versions of @code{pcb} used mils
144 (1/1000 inch) as the base unit; a value of 500 in the file meant
145 half an inch. Newer versions uses a "high resolution" syntax,
146 where the base unit is 1/100 of a mil (0.000010 inch); a value of 500 in
147 the file means 5 mils. As a general rule, the variants of each entry
148 listed below which use square brackets are the high resolution formats
149 and use the 1/100 mil units, and the ones with parentheses are the older
150 variants and use 1 mil units. Note that when multiple variants
151 are listed, the most recent (and most preferred) format is the first
154 Symbolic and numeric flags (SFlags and NFlags) are described in
161 /* reset flags for 'used layers';
162 * init font and data pointers
168 Message
(_
("illegal fileformat\n"));
171 for
(i
= 0; i
< MAX_LAYER
+ 2; i
++)
172 LayerFlag
[i
] = false
;
173 yyFont
= &yyPCB
->Font
;
174 yyData
= yyPCB
->Data
;
177 /* Parse the default layer group string, just in case the file doesn't have one */
178 if
(ParseGroupString
(Settings.Groups
, &yyPCB
->LayerGroups
, &yyData
->LayerN
))
180 Message
(_
("illegal default layer-group string\n"));
198 PCBType
*pcb_save
= PCB
;
200 CreateNewPCBPost
(yyPCB
, 0);
201 /* initialize the polygon clipping now since
202 * we didn't know the layer grouping before.
205 ALLPOLYGON_LOOP
(yyData
);
207 InitClip
(yyData
, layer
, polygon
);
216 /* This case is when we load a footprint with file->open, or from the command line */
217 yyFont
= &yyPCB
->Font
;
218 yyData
= yyPCB
->Data
;
225 PCBType
*pcb_save
= PCB
;
229 /* This case is when we load a footprint with file->open, or from the command line */
230 CreateNewPCBPost
(yyPCB
, 0);
231 ParseGroupString
("1,c:2,s", &yyPCB
->LayerGroups
, &yyData
->LayerN
);
232 e
= yyPCB
->Data
->Element
->data
; /* we know there's only one */
234 MoveElementLowLevel
(yyPCB
->Data
, e
, -e
->BoundingBox.X1
, -e
->BoundingBox.Y1
);
236 yyPCB
->MaxWidth
= e
->BoundingBox.X2
;
237 yyPCB
->MaxHeight
= e
->BoundingBox.Y2
;
238 yyPCB
->is_footprint
= 1;
245 /* reset flags for 'used layers';
246 * init font and data pointers
250 if
(!yyData ||
!yyFont
)
252 Message
(_
("illegal fileformat\n"));
255 for
(i
= 0; i
< MAX_LAYER
+ 2; i
++)
256 LayerFlag
[i
] = false
;
270 /* mark all symbols invalid */
275 Message
(_
("illegal fileformat\n"));
278 yyFont
->Valid
= false
;
279 for
(i
= 0; i
<= MAX_FONTPOSITION
; i
++)
280 free
(yyFont
->Symbol
[i
].Line
);
281 bzero
(yyFont
->Symbol
, sizeof
(yyFont
->Symbol
));
285 yyFont
->Valid
= true
;
290 /* %start-doc pcbfile FileVersion
298 File format version. This version number represents the date when the pcb file
299 format was last changed.
302 Any version of pcb build from sources equal to or newer
303 than this number should be able to read the file. If this line is not present
304 in the input file then file format compatibility is not checked.
311 T_FILEVERSION
'[' INTEGER
']'
313 if
(check_file_version
($3) != 0)
320 /* %start-doc pcbfile PCB
323 PCB ["Name" Width Height]
324 PCB ("Name" Width Height]
330 Name of the PCB project
335 If you don't specify the size of the board, a very large default is
341 : T_PCB
'(' STRING
')'
344 yyPCB
->MaxWidth
= MAX_COORD
;
345 yyPCB
->MaxHeight
= MAX_COORD
;
347 | T_PCB
'(' STRING measure measure
')'
350 yyPCB
->MaxWidth
= OU
($4);
351 yyPCB
->MaxHeight
= OU
($5);
353 | T_PCB
'[' STRING measure measure
']'
356 yyPCB
->MaxWidth
= NU
($4);
357 yyPCB
->MaxHeight
= NU
($5);
361 /* %start-doc pcbfile Grid
364 Grid [Step OffsetX OffsetY Visible]
365 Grid (Step OffsetX OffsetY Visible)
366 Grid (Step OffsetX OffsetY)
371 Distance from one grid point to adjacent points. This value may be a
372 floating point number for the first two variants.
373 @item OffsetX OffsetY
374 The "origin" of the grid. Normally zero.
376 If non-zero, the grid will be visible on the screen.
387 : T_GRID
'(' measure measure measure
')'
389 yyPCB
->Grid
= OU
($3);
390 yyPCB
->GridOffsetX
= OU
($4);
391 yyPCB
->GridOffsetY
= OU
($5);
395 : T_GRID
'(' measure measure measure INTEGER
')'
397 yyPCB
->Grid
= OU
($3);
398 yyPCB
->GridOffsetX
= OU
($4);
399 yyPCB
->GridOffsetY
= OU
($5);
401 Settings.DrawGrid
= true
;
403 Settings.DrawGrid
= false
;
408 : T_GRID
'[' measure measure measure INTEGER
']'
410 yyPCB
->Grid
= NU
($3);
411 yyPCB
->GridOffsetX
= NU
($4);
412 yyPCB
->GridOffsetY
= NU
($5);
414 Settings.DrawGrid
= true
;
416 Settings.DrawGrid
= false
;
420 /* %start-doc pcbfile Cursor
429 Location of the cursor when the board was saved.
430 As of November 2012 the cursor position is not written to file anymore.
431 Older versions of pcb ignore the absence of this line in the pcb file.
433 The current zoom factor. Note that a zoom factor of "0" means 1 mil
434 per screen pixel, N means @math{2^N} mils per screen pixel, etc. The
435 first variant accepts floating point numbers. The special value
436 "1000" means "zoom to fit"
438 This field is ignored by PCB.
444 : T_CURSOR
'(' measure measure number
')'
446 yyPCB
->CursorX
= OU
($3);
447 yyPCB
->CursorY
= OU
($4);
449 | T_CURSOR
'[' measure measure number
']'
451 yyPCB
->CursorX
= NU
($3);
452 yyPCB
->CursorY
= NU
($4);
457 /* %start-doc pcbfile PolyArea
465 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.
472 | T_AREA
'[' number
']'
474 /* Read in cmil^2 for now; in future this should be a noop. */
475 yyPCB
->IsleArea
= MIL_TO_COORD
(MIL_TO_COORD
($3) / 100.0) / 100.0;
480 /* %start-doc pcbfile Thermal
488 Relative size of thermal fingers. A value of 1.0 makes the finger
489 width twice the clearance gap width (measured across the gap, not
490 diameter). The normal value is 0.5, which results in a finger width
491 the same as the clearance gap width.
499 | T_THERMAL
'[' number
']'
501 yyPCB
->ThermScale
= $3;
505 /* %start-doc pcbfile DRC
508 DRC [Bloat Shrink Line Silk Drill Ring]
509 DRC [Bloat Shrink Line Silk]
510 DRC [Bloat Shrink Line]
515 Minimum spacing between copper.
517 Minimum copper overlap to guarantee connectivity.
519 Minimum line thickness.
521 Minimum silk thickness.
525 Minimum width of the annular ring around pins and vias.
538 : T_DRC
'[' measure measure measure
']'
540 yyPCB
->Bloat
= NU
($3);
541 yyPCB
->Shrink
= NU
($4);
542 yyPCB
->minWid
= NU
($5);
543 yyPCB
->minRing
= NU
($5);
548 : T_DRC
'[' measure measure measure measure
']'
550 yyPCB
->Bloat
= NU
($3);
551 yyPCB
->Shrink
= NU
($4);
552 yyPCB
->minWid
= NU
($5);
553 yyPCB
->minSlk
= NU
($6);
554 yyPCB
->minRing
= NU
($5);
559 : T_DRC
'[' measure measure measure measure measure measure
']'
561 yyPCB
->Bloat
= NU
($3);
562 yyPCB
->Shrink
= NU
($4);
563 yyPCB
->minWid
= NU
($5);
564 yyPCB
->minSlk
= NU
($6);
565 yyPCB
->minDrill
= NU
($7);
566 yyPCB
->minRing
= NU
($8);
570 /* %start-doc pcbfile Flags
578 A number, whose value is normally given in hex, individual bits of which
579 represent pcb-wide flags as defined in @ref{PCBFlags}.
586 : T_FLAGS
'(' INTEGER
')'
588 yyPCB
->Flags
= MakeFlags
($3 & PCB_FLAGS
);
590 | T_FLAGS
'(' STRING
')'
592 yyPCB
->Flags
= string_to_pcbflags
($3, yyerror);
597 /* %start-doc pcbfile Groups
606 Encodes the layer grouping information. Each group is separated by a
607 colon, each member of each group is separated by a comma. Group
608 members are either numbers from @code{1}..@var{N} for each layer, and
609 the letters @code{c} or @code{s} representing the component side and
610 solder side of the board. Including @code{c} or @code{s} marks that
611 group as being the top or bottom side of the board.
614 Groups("1,2,c:3:4:5,6,s:7,8")
622 : T_GROUPS
'(' STRING
')'
624 if
(ParseGroupString
($3, &yyPCB
->LayerGroups
, &yyData
->LayerN
))
626 Message
(_
("illegal layer-group string\n"));
633 /* %start-doc pcbfile Styles
642 Encodes the four routing styles @code{pcb} knows about. The four styles
643 are separated by colons. Each style consists of five parameters as follows:
647 The name of the style.
649 Width of lines and arcs.
651 Copper diameter of pins and vias.
653 Drill diameter of pins and vias.
655 Minimum spacing to other nets. If omitted, 10 mils is the default.
662 Styles("Signal,10,40,20:Power,25,60,35:Fat,40,60,35:Skinny,8,36,20")
663 Styles["Logic,1000,3600,2000,1000:Power,2500,6000,3500,1000:
664 @ @ @ Line,4000,6000,3500,1000:Breakout,600,2402,1181,600"]
668 Note that strings in actual files cannot span lines; the above example
669 is split across lines only to make it readable.
674 : T_STYLES
'(' STRING
')'
676 if
(ParseRouteString
($3, &yyPCB
->RouteStyle
[0], "mil"))
678 Message
(_
("illegal route-style string\n"));
682 | T_STYLES
'[' STRING
']'
684 if
(ParseRouteString
($3, &yyPCB
->RouteStyle
[0], "cmil"))
686 Message
(_
("illegal route-style string\n"));
700 | pcbdefinitions pcbdefinition
705 |
{ attr_list
= & yyPCB
->Attributes
; } attribute
720 /* %start-doc pcbfile Via
723 Via [X Y Thickness Clearance Mask Drill "Name" SFlags]
724 Via (X Y Thickness Clearance Mask Drill "Name" NFlags)
725 Via (X Y Thickness Clearance Drill "Name" NFlags)
726 Via (X Y Thickness Drill "Name" NFlags)
727 Via (X Y Thickness "Name" NFlags)
732 coordinates of center
734 outer diameter of copper annulus
736 add to thickness to get clearance diameter
738 diameter of solder mask opening
742 string, name of via (vias have names?)
744 symbolic or numerical flags
752 /* x, y, thickness, clearance, mask, drilling-hole, name, flags */
753 : T_VIA
'[' measure measure measure measure measure measure STRING flags
']'
755 CreateNewVia
(yyData
, NU
($3), NU
($4), NU
($5), NU
($6), NU
($7),
762 /* x, y, thickness, clearance, mask, drilling-hole, name, flags */
763 : T_VIA
'(' measure measure measure measure measure measure STRING INTEGER
')'
765 CreateNewVia
(yyData
, OU
($3), OU
($4), OU
($5), OU
($6), OU
($7), OU
($8), $9,
773 /* x, y, thickness, clearance, drilling-hole, name, flags */
774 : T_VIA
'(' measure measure measure measure measure STRING INTEGER
')'
776 CreateNewVia
(yyData
, OU
($3), OU
($4), OU
($5), OU
($6),
777 OU
($5) + OU
($6), OU
($7), $8, OldFlags
($9));
783 /* x, y, thickness, drilling-hole, name, flags */
784 : T_VIA
'(' measure measure measure measure STRING INTEGER
')'
786 CreateNewVia
(yyData
, OU
($3), OU
($4), OU
($5), 2*GROUNDPLANEFRAME
,
787 OU
($5) + 2*MASKFRAME
, OU
($6), $7, OldFlags
($8));
793 /* old format: x, y, thickness, name, flags */
794 : T_VIA
'(' measure measure measure STRING INTEGER
')'
796 Coord hole
= (OU
($5) * DEFAULT_DRILLINGHOLE
);
798 /* make sure that there's enough copper left */
799 if
(OU
($5) - hole
< MIN_PINORVIACOPPER
&&
800 OU
($5) > MIN_PINORVIACOPPER
)
801 hole
= OU
($5) - MIN_PINORVIACOPPER
;
803 CreateNewVia
(yyData
, OU
($3), OU
($4), OU
($5), 2*GROUNDPLANEFRAME
,
804 OU
($5) + 2*MASKFRAME
, hole
, $6, OldFlags
($7));
809 /* %start-doc pcbfile Rat
812 Rat [X1 Y1 Group1 X2 Y2 Group2 SFlags]
813 Rat (X1 Y1 Group1 X2 Y2 Group2 NFlags)
818 The endpoints of the rat line.
820 The layer group each end is connected on.
822 Symbolic or numeric flags.
830 : T_RAT
'[' measure measure INTEGER measure measure INTEGER flags
']'
832 CreateNewRat
(yyData
, NU
($3), NU
($4), NU
($6), NU
($7), $5, $8,
833 Settings.RatThickness
, $9);
835 | T_RAT
'(' measure measure INTEGER measure measure INTEGER INTEGER
')'
837 CreateNewRat
(yyData
, OU
($3), OU
($4), OU
($6), OU
($7), $5, $8,
838 Settings.RatThickness
, OldFlags
($9));
842 /* %start-doc pcbfile Layer
845 Layer (LayerNum "Name") (
846 @ @ @ @dots{} contents @dots{}
852 The layer number. Layers are numbered sequentially, starting with 1.
853 The last two layers (9 and 10 by default) are solder-side silk and
854 component-side silk, in that order.
858 The contents of the layer, which may include attributes, lines, arcs, rectangles,
866 : T_LAYER
'(' INTEGER STRING opt_string
')' '('
868 if
($3 <= 0 ||
$3 > MAX_LAYER
+ 2)
870 yyerror("Layernumber out of range");
875 yyerror("Layernumber used twice");
878 Layer
= &yyData
->Layer
[$3-1];
880 /* memory for name is already allocated */
882 if
(Layer
->Name
== NULL
)
883 Layer
->Name
= strdup
("");
884 LayerFlag
[$3-1] = true
;
896 | layerdefinitions layerdefinition
906 /* x1, y1, x2, y2, flags */
907 | T_RECTANGLE
'(' measure measure measure measure INTEGER
')'
909 CreateNewPolygonFromRectangle
(Layer
,
910 OU
($3), OU
($4), OU
($3) + OU
($5), OU
($4) + OU
($6), OldFlags
($7));
915 |
{ attr_list
= & Layer
->Attributes
; } attribute
918 /* %start-doc pcbfile Line
921 Line [X1 Y1 X2 Y2 Thickness Clearance SFlags]
922 Line (X1 Y1 X2 Y2 Thickness Clearance NFlags)
923 Line (X1 Y1 X2 Y2 Thickness NFlags)
928 The end points of the line
930 The width of the line
932 The amount of space cleared around the line when the line passes
933 through a polygon. The clearance is added to the thickness to get the
934 thickness of the clear; thus the space between the line and the
935 polygon is @math{Clearance/2} wide.
937 Symbolic or numeric flags
945 /* x1, y1, x2, y2, thickness, clearance, flags */
946 : T_LINE
'[' measure measure measure measure measure measure flags
']'
948 CreateNewLineOnLayer
(Layer
, NU
($3), NU
($4), NU
($5), NU
($6),
949 NU
($7), NU
($8), $9);
954 /* x1, y1, x2, y2, thickness, clearance, flags */
955 : T_LINE
'(' measure measure measure measure measure measure INTEGER
')'
957 CreateNewLineOnLayer
(Layer
, OU
($3), OU
($4), OU
($5), OU
($6),
958 OU
($7), OU
($8), OldFlags
($9));
963 /* x1, y1, x2, y2, thickness, flags */
964 : T_LINE
'(' measure measure measure measure measure measure
')'
966 /* eliminate old-style rat-lines */
967 if
((IV
($8) & RATFLAG
) == 0)
968 CreateNewLineOnLayer
(Layer
, OU
($3), OU
($4), OU
($5), OU
($6), OU
($7),
969 200*GROUNDPLANEFRAME
, OldFlags
(IV
($8)));
973 /* %start-doc pcbfile Arc
976 Arc [X Y Width Height Thickness Clearance StartAngle DeltaAngle SFlags]
977 Arc (X Y Width Height Thickness Clearance StartAngle DeltaAngle NFlags)
978 Arc (X Y Width Height Thickness StartAngle DeltaAngle NFlags)
983 Coordinates of the center of the arc.
985 The width and height, from the center to the edge. The bounds of the
986 circle of which this arc is a segment, is thus @math{2*Width} by
989 The width of the copper trace which forms the arc.
991 The amount of space cleared around the arc when the line passes
992 through a polygon. The clearance is added to the thickness to get the
993 thickness of the clear; thus the space between the arc and the polygon
994 is @math{Clearance/2} wide.
996 The angle of one end of the arc, in degrees. In PCB, an angle of zero
997 points left (negative X direction), and 90 degrees points down
998 (positive Y direction).
1000 The sweep of the arc. This may be negative. Positive angles sweep
1003 Symbolic or numeric flags.
1011 /* x, y, width, height, thickness, clearance, startangle, delta, flags */
1012 : T_ARC
'[' measure measure measure measure measure measure number number flags
']'
1014 CreateNewArcOnLayer
(Layer
, NU
($3), NU
($4), NU
($5), NU
($6), $9, $10,
1015 NU
($7), NU
($8), $11);
1020 /* x, y, width, height, thickness, clearance, startangle, delta, flags */
1021 : T_ARC
'(' measure measure measure measure measure measure number number INTEGER
')'
1023 CreateNewArcOnLayer
(Layer
, OU
($3), OU
($4), OU
($5), OU
($6), $9, $10,
1024 OU
($7), OU
($8), OldFlags
($11));
1029 /* x, y, width, height, thickness, startangle, delta, flags */
1030 : T_ARC
'(' measure measure measure measure measure measure number INTEGER
')'
1032 CreateNewArcOnLayer
(Layer
, OU
($3), OU
($4), OU
($5), OU
($5), IV
($8), $9,
1033 OU
($7), 200*GROUNDPLANEFRAME
, OldFlags
($10));
1037 /* %start-doc pcbfile Text
1040 Text [X Y Direction Scale "String" SFlags]
1041 Text (X Y Direction Scale "String" NFlags)
1042 Text (X Y Direction "String" NFlags)
1047 The location of the upper left corner of the text.
1049 0 means text is drawn left to right, 1 means up, 2 means right to left
1050 (i.e. upside down), and 3 means down.
1052 Size of the text, as a percentage of the ``default'' size of of the
1053 font (the default font is about 40 mils high). Default is 100 (40
1058 Symbolic or numeric flags.
1066 /* x, y, direction, text, flags */
1067 : T_TEXT
'(' measure measure number STRING INTEGER
')'
1069 /* use a default scale of 100% */
1070 CreateNewText
(Layer
,yyFont
,OU
($3), OU
($4), $5, 100, $6, OldFlags
($7));
1076 /* x, y, direction, scale, text, flags */
1077 : T_TEXT
'(' measure measure number number STRING INTEGER
')'
1079 if
($8 & ONSILKFLAG
)
1081 LayerType
*lay
= &yyData
->Layer
[yyData
->LayerN
+
1082 (($8 & ONSOLDERFLAG
) ? BOTTOM_SILK_LAYER
: TOP_SILK_LAYER
)];
1084 CreateNewText
(lay
,yyFont
, OU
($3), OU
($4), $5, $6, $7,
1088 CreateNewText
(Layer
, yyFont
, OU
($3), OU
($4), $5, $6, $7,
1094 /* x, y, direction, scale, text, flags */
1095 : T_TEXT
'[' measure measure number number STRING flags
']'
1097 /* FIXME: shouldn't know about .f */
1098 /* I don't think this matters because anything with hi_format
1099 * will have the silk on its own layer in the file rather
1100 * than using the ONSILKFLAG and having it in a copper layer.
1101 * Thus there is no need for anything besides the 'else'
1102 * part of this code.
1104 if
($8.f
& ONSILKFLAG
)
1106 LayerType
*lay
= &yyData
->Layer
[yyData
->LayerN
+
1107 (($8.f
& ONSOLDERFLAG
) ? BOTTOM_SILK_LAYER
: TOP_SILK_LAYER
)];
1109 CreateNewText
(lay
, yyFont
, NU
($3), NU
($4), $5, $6, $7, $8);
1112 CreateNewText
(Layer
, yyFont
, NU
($3), NU
($4), $5, $6, $7, $8);
1117 /* %start-doc pcbfile Polygon
1121 @ @ @ @dots{} (X Y) @dots{}
1122 @ @ @ @dots{} [X Y] @dots{}
1124 @ @ @ @ @ @ @dots{} (X Y) @dots{}
1125 @ @ @ @ @ @ @dots{} [X Y] @dots{}
1133 Symbolic or numeric flags.
1135 Coordinates of each vertex. You must list at least three coordinates.
1137 Defines a hole within the polygon's outer contour. There may be zero or more such sections.
1143 : /* flags are passed in */
1144 T_POLYGON
'(' flags
')' '('
1146 Polygon
= CreateNewPolygon
(Layer
, $3);
1151 Cardinal contour
, contour_start
, contour_end
;
1152 bool bad_contour_found
= false
;
1154 for
(contour
= 0; contour
<= Polygon
->HoleIndexN
; contour
++)
1156 contour_start
= (contour
== 0) ?
1157 0 : Polygon
->HoleIndex
[contour
- 1];
1158 contour_end
= (contour
== Polygon
->HoleIndexN
) ?
1160 Polygon
->HoleIndex
[contour
];
1161 if
(contour_end
- contour_start
< 3)
1162 bad_contour_found
= true
;
1165 if
(bad_contour_found
)
1167 Message
(_
("WARNING parsing file '%s'\n"
1169 " description: 'ignored polygon "
1170 "(< 3 points in a contour)'\n"),
1171 yyfilename
, yylineno
);
1172 DestroyObject
(yyData
, POLYGON_TYPE
, Layer
, Polygon
, Polygon
);
1176 SetPolygonBoundingBox
(Polygon
);
1177 if
(!Layer
->polygon_tree
)
1178 Layer
->polygon_tree
= r_create_tree
(NULL
, 0, 0);
1179 r_insert_entry
(Layer
->polygon_tree
, (BoxType
*) Polygon
, 0);
1186 | polygonholes polygonhole
1190 : T_POLYGON_HOLE
'('
1192 CreateNewHoleInPolygon
(Polygon
);
1199 | polygonpoint polygonpoints
1204 : '(' measure measure
')'
1206 CreateNewPointInPolygon
(Polygon
, OU
($2), OU
($3));
1208 |
'[' measure measure
']'
1210 CreateNewPointInPolygon
(Polygon
, NU
($2), NU
($3));
1214 /* %start-doc pcbfile Element
1217 Element [SFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TSFlags] (
1218 Element (NFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TNFlags) (
1219 Element (NFlags "Desc" "Name" "Value" TX TY TDir TScale TNFlags) (
1220 Element (NFlags "Desc" "Name" TX TY TDir TScale TNFlags) (
1221 Element ("Desc" "Name" TX TY TDir TScale TNFlags) (
1222 @ @ @ @dots{} contents @dots{}
1228 Symbolic or numeric flags, for the element as a whole.
1230 Numeric flags, for the element as a whole.
1232 The description of the element. This is one of the three strings
1233 which can be displayed on the screen.
1235 The name of the element, usually the reference designator.
1237 The value of the element.
1239 The location of the element's mark. This is the reference point
1240 for placing the element and its pins and pads.
1242 The upper left corner of the text (one of the three strings).
1244 The relative direction of the text. 0 means left to right for
1245 an unrotated element, 1 means up, 2 left, 3 down.
1247 Size of the text, as a percentage of the ``default'' size of of the
1248 font (the default font is about 40 mils high). Default is 100 (40
1251 Symbolic or numeric flags, for the text.
1253 Numeric flags, for the text.
1256 Elements may contain pins, pads, element lines, element arcs,
1257 attributes, and (for older elements) an optional mark. Note that
1258 element definitions that have the mark coordinates in the element
1259 line, only support pins and pads which use relative coordinates. The
1260 pin and pad coordinates are relative to the mark. Element definitions
1261 which do not include the mark coordinates in the element line, may
1262 have a Mark definition in their contents, and only use pin and pad
1263 definitions which use absolute coordinates.
1269 | element_1.3
.4_format
1271 | element_1.7_format
1276 /* element_flags, description, pcb-name,
1277 * text_x, text_y, text_direction, text_scale, text_flags
1279 : T_ELEMENT
'(' STRING STRING measure measure INTEGER
')' '('
1281 yyElement
= CreateNewElement
(yyData
, yyFont
, NoFlags
(),
1282 $3, $4, NULL
, OU
($5), OU
($6), $7, 100, NoFlags
(), false
);
1287 elementdefinitions
')'
1289 SetElementBoundingBox
(yyData
, yyElement
, yyFont
);
1293 element_1.3
.4_format
1294 /* element_flags, description, pcb-name,
1295 * text_x, text_y, text_direction, text_scale, text_flags
1297 : T_ELEMENT
'(' INTEGER STRING STRING measure measure measure measure INTEGER
')' '('
1299 yyElement
= CreateNewElement
(yyData
, yyFont
, OldFlags
($3),
1300 $4, $5, NULL
, OU
($6), OU
($7), IV
($8), IV
($9), OldFlags
($10), false
);
1305 elementdefinitions
')'
1307 SetElementBoundingBox
(yyData
, yyElement
, yyFont
);
1312 /* element_flags, description, pcb-name, value,
1313 * text_x, text_y, text_direction, text_scale, text_flags
1315 : T_ELEMENT
'(' INTEGER STRING STRING STRING measure measure measure measure INTEGER
')' '('
1317 yyElement
= CreateNewElement
(yyData
, yyFont
, OldFlags
($3),
1318 $4, $5, $6, OU
($7), OU
($8), IV
($9), IV
($10), OldFlags
($11), false
);
1324 elementdefinitions
')'
1326 SetElementBoundingBox
(yyData
, yyElement
, yyFont
);
1331 /* element_flags, description, pcb-name, value, mark_x, mark_y,
1332 * text_x, text_y, text_direction, text_scale, text_flags
1334 : T_ELEMENT
'(' INTEGER STRING STRING STRING measure measure
1335 measure measure number number INTEGER
')' '('
1337 yyElement
= CreateNewElement
(yyData
, yyFont
, OldFlags
($3),
1338 $4, $5, $6, OU
($7) + OU
($9), OU
($8) + OU
($10),
1339 $11, $12, OldFlags
($13), false
);
1340 yyElement
->MarkX
= OU
($7);
1341 yyElement
->MarkY
= OU
($8);
1348 SetElementBoundingBox
(yyData
, yyElement
, yyFont
);
1353 /* element_flags, description, pcb-name, value, mark_x, mark_y,
1354 * text_x, text_y, text_direction, text_scale, text_flags
1356 : T_ELEMENT
'[' flags STRING STRING STRING measure measure
1357 measure measure number number flags
']' '('
1359 yyElement
= CreateNewElement
(yyData
, yyFont
, $3,
1360 $4, $5, $6, NU
($7) + NU
($9), NU
($8) + NU
($10),
1361 $11, $12, $13, false
);
1362 yyElement
->MarkX
= NU
($7);
1363 yyElement
->MarkY
= NU
($8);
1370 SetElementBoundingBox
(yyData
, yyElement
, yyFont
);
1374 /* %start-doc pcbfile ElementLine
1377 ElementLine [X1 Y1 X2 Y2 Thickness]
1378 ElementLine (X1 Y1 X2 Y2 Thickness)
1383 Coordinates of the endpoints of the line. These are relative to the
1384 Element's mark point for new element formats, or absolute for older
1387 The width of the silk for this line.
1392 /* %start-doc pcbfile ElementArc
1395 ElementArc [X Y Width Height StartAngle DeltaAngle Thickness]
1396 ElementArc (X Y Width Height StartAngle DeltaAngle Thickness)
1401 Coordinates of the center of the arc. These are relative to the
1402 Element's mark point for new element formats, or absolute for older
1405 The width and height, from the center to the edge. The bounds of the
1406 circle of which this arc is a segment, is thus @math{2*Width} by
1409 The angle of one end of the arc, in degrees. In PCB, an angle of zero
1410 points left (negative X direction), and 90 degrees points down
1411 (positive Y direction).
1413 The sweep of the arc. This may be negative. Positive angles sweep
1416 The width of the silk line which forms the arc.
1421 /* %start-doc pcbfile Mark
1430 Coordinates of the Mark, for older element formats that don't have
1431 the mark as part of the Element line.
1438 | elementdefinitions elementdefinition
1447 /* x1, y1, x2, y2, thickness */
1448 | T_ELEMENTLINE
'[' measure measure measure measure measure
']'
1450 CreateNewLineInElement
(yyElement
, NU
($3), NU
($4), NU
($5), NU
($6), NU
($7));
1452 /* x1, y1, x2, y2, thickness */
1453 | T_ELEMENTLINE
'(' measure measure measure measure measure
')'
1455 CreateNewLineInElement
(yyElement
, OU
($3), OU
($4), OU
($5), OU
($6), OU
($7));
1457 /* x, y, width, height, startangle, anglediff, thickness */
1458 | T_ELEMENTARC
'[' measure measure measure measure number number measure
']'
1460 CreateNewArcInElement
(yyElement
, NU
($3), NU
($4), NU
($5), NU
($6), $7, $8, NU
($9));
1462 /* x, y, width, height, startangle, anglediff, thickness */
1463 | T_ELEMENTARC
'(' measure measure measure measure number number measure
')'
1465 CreateNewArcInElement
(yyElement
, OU
($3), OU
($4), OU
($5), OU
($6), $7, $8, OU
($9));
1468 | T_MARK
'[' measure measure
']'
1470 yyElement
->MarkX
= NU
($3);
1471 yyElement
->MarkY
= NU
($4);
1473 | T_MARK
'(' measure measure
')'
1475 yyElement
->MarkX
= OU
($3);
1476 yyElement
->MarkY
= OU
($4);
1478 |
{ attr_list
= & yyElement
->Attributes
; } attribute
1483 | relementdefs relementdef
1491 /* x1, y1, x2, y2, thickness */
1492 | T_ELEMENTLINE
'[' measure measure measure measure measure
']'
1494 CreateNewLineInElement
(yyElement
, NU
($3) + yyElement
->MarkX
,
1495 NU
($4) + yyElement
->MarkY
, NU
($5) + yyElement
->MarkX
,
1496 NU
($6) + yyElement
->MarkY
, NU
($7));
1498 | T_ELEMENTLINE
'(' measure measure measure measure measure
')'
1500 CreateNewLineInElement
(yyElement
, OU
($3) + yyElement
->MarkX
,
1501 OU
($4) + yyElement
->MarkY
, OU
($5) + yyElement
->MarkX
,
1502 OU
($6) + yyElement
->MarkY
, OU
($7));
1504 /* x, y, width, height, startangle, anglediff, thickness */
1505 | T_ELEMENTARC
'[' measure measure measure measure number number measure
']'
1507 CreateNewArcInElement
(yyElement
, NU
($3) + yyElement
->MarkX
,
1508 NU
($4) + yyElement
->MarkY
, NU
($5), NU
($6), $7, $8, NU
($9));
1510 | T_ELEMENTARC
'(' measure measure measure measure number number measure
')'
1512 CreateNewArcInElement
(yyElement
, OU
($3) + yyElement
->MarkX
,
1513 OU
($4) + yyElement
->MarkY
, OU
($5), OU
($6), $7, $8, OU
($9));
1515 |
{ attr_list
= & yyElement
->Attributes
; } attribute
1518 /* %start-doc pcbfile Pin
1521 Pin [rX rY Thickness Clearance Mask Drill "Name" "Number" SFlags]
1522 Pin (rX rY Thickness Clearance Mask Drill "Name" "Number" NFlags)
1523 Pin (aX aY Thickness Drill "Name" "Number" NFlags)
1524 Pin (aX aY Thickness Drill "Name" NFlags)
1525 Pin (aX aY Thickness "Name" NFlags)
1530 coordinates of center, relative to the element's mark
1532 absolute coordinates of center.
1534 outer diameter of copper annulus
1536 add to thickness to get clearance diameter
1538 diameter of solder mask opening
1546 symbolic or numerical flags
1548 numerical flags only
1554 /* x, y, thickness, clearance, mask, drilling hole, name,
1556 : T_PIN
'[' measure measure measure measure measure measure STRING STRING flags
']'
1558 CreateNewPin
(yyElement
, NU
($3) + yyElement
->MarkX
,
1559 NU
($4) + yyElement
->MarkY
, NU
($5), NU
($6), NU
($7), NU
($8), $9,
1566 /* x, y, thickness, clearance, mask, drilling hole, name,
1568 : T_PIN
'(' measure measure measure measure measure measure STRING STRING INTEGER
')'
1570 CreateNewPin
(yyElement
, OU
($3) + yyElement
->MarkX
,
1571 OU
($4) + yyElement
->MarkY
, OU
($5), OU
($6), OU
($7), OU
($8), $9,
1572 $10, OldFlags
($11));
1579 /* x, y, thickness, drilling hole, name, number, flags */
1580 : T_PIN
'(' measure measure measure measure STRING STRING INTEGER
')'
1582 CreateNewPin
(yyElement
, OU
($3), OU
($4), OU
($5), 2*GROUNDPLANEFRAME
,
1583 OU
($5) + 2*MASKFRAME
, OU
($6), $7, $8, OldFlags
($9));
1590 /* x, y, thickness, drilling hole, name, flags */
1591 : T_PIN
'(' measure measure measure measure STRING INTEGER
')'
1595 sprintf
(p_number
, "%d", pin_num
++);
1596 CreateNewPin
(yyElement
, OU
($3), OU
($4), OU
($5), 2*GROUNDPLANEFRAME
,
1597 OU
($5) + 2*MASKFRAME
, OU
($6), $7, p_number
, OldFlags
($8));
1604 /* old format: x, y, thickness, name, flags
1605 * drilling hole is 40% of the diameter
1607 : T_PIN
'(' measure measure measure STRING INTEGER
')'
1609 Coord hole
= OU
($5) * DEFAULT_DRILLINGHOLE
;
1612 /* make sure that there's enough copper left */
1613 if
(OU
($5) - hole
< MIN_PINORVIACOPPER
&&
1614 OU
($5) > MIN_PINORVIACOPPER
)
1615 hole
= OU
($5) - MIN_PINORVIACOPPER
;
1617 sprintf
(p_number
, "%d", pin_num
++);
1618 CreateNewPin
(yyElement
, OU
($3), OU
($4), OU
($5), 2*GROUNDPLANEFRAME
,
1619 OU
($5) + 2*MASKFRAME
, hole
, $6, p_number
, OldFlags
($7));
1624 /* %start-doc pcbfile Pad
1627 Pad [rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" SFlags]
1628 Pad (rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" NFlags)
1629 Pad (aX1 aY1 aX2 aY2 Thickness "Name" "Number" NFlags)
1630 Pad (aX1 aY1 aX2 aY2 Thickness "Name" NFlags)
1634 @item rX1 rY1 rX2 rY2
1635 Coordinates of the endpoints of the pad, relative to the element's
1636 mark. Note that the copper extends beyond these coordinates by half
1637 the thickness. To make a square or round pad, specify the same
1639 @item aX1 aY1 aX2 aY2
1640 Same, but absolute coordinates of the endpoints of the pad.
1644 add to thickness to get clearance width.
1646 width of solder mask opening.
1652 symbolic or numerical flags
1654 numerical flags only
1660 /* x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags */
1661 : T_PAD
'[' measure measure measure measure measure measure measure STRING STRING flags
']'
1663 CreateNewPad
(yyElement
, NU
($3) + yyElement
->MarkX
,
1664 NU
($4) + yyElement
->MarkY
,
1665 NU
($5) + yyElement
->MarkX
,
1666 NU
($6) + yyElement
->MarkY
, NU
($7), NU
($8), NU
($9),
1674 /* x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags */
1675 : T_PAD
'(' measure measure measure measure measure measure measure STRING STRING INTEGER
')'
1677 CreateNewPad
(yyElement
,OU
($3) + yyElement
->MarkX
,
1678 OU
($4) + yyElement
->MarkY
, OU
($5) + yyElement
->MarkX
,
1679 OU
($6) + yyElement
->MarkY
, OU
($7), OU
($8), OU
($9),
1680 $10, $11, OldFlags
($12));
1687 /* x1, y1, x2, y2, thickness, name , pad number, flags */
1688 : T_PAD
'(' measure measure measure measure measure STRING STRING INTEGER
')'
1690 CreateNewPad
(yyElement
,OU
($3),OU
($4),OU
($5),OU
($6),OU
($7), 2*GROUNDPLANEFRAME
,
1691 OU
($7) + 2*MASKFRAME
, $8, $9, OldFlags
($10));
1698 /* x1, y1, x2, y2, thickness, name and flags */
1699 : T_PAD
'(' measure measure measure measure measure STRING INTEGER
')'
1703 sprintf
(p_number
, "%d", pin_num
++);
1704 CreateNewPad
(yyElement
,OU
($3),OU
($4),OU
($5),OU
($6),OU
($7), 2*GROUNDPLANEFRAME
,
1705 OU
($7) + 2*MASKFRAME
, $8,p_number
, OldFlags
($9));
1710 flags
: INTEGER
{ $$
= OldFlags
($1); }
1711 | STRING
{ $$
= string_to_flags
($1, yyerror); }
1719 /* %start-doc pcbfile Symbol
1722 Symbol [Char Delta] (
1723 Symbol (Char Delta) (
1724 @ @ @ @dots{} symbol lines @dots{}
1730 The character or numerical character value this symbol represents.
1731 Characters must be in single quotes.
1733 Additional space to allow after this character.
1738 symbol
: symbolhead symboldata
')'
1740 symbolhead
: T_SYMBOL
'[' symbolid measure
']' '('
1742 if
($3 <= 0 ||
$3 > MAX_FONTPOSITION
)
1744 yyerror("fontposition out of range");
1747 Symbol
= &yyFont
->Symbol
[$3];
1750 yyerror("symbol ID used twice");
1753 Symbol
->Valid
= true
;
1754 Symbol
->Delta
= NU
($4);
1756 | T_SYMBOL
'(' symbolid measure
')' '('
1758 if
($3 <= 0 ||
$3 > MAX_FONTPOSITION
)
1760 yyerror("fontposition out of range");
1763 Symbol
= &yyFont
->Symbol
[$3];
1766 yyerror("symbol ID used twice");
1769 Symbol
->Valid
= true
;
1770 Symbol
->Delta
= OU
($4);
1781 | symboldata symboldefinition
1782 | symboldata hiressymbol
1785 /* %start-doc pcbfile SymbolLine
1788 SymbolLine [X1 Y1 X2 Y2 Thickness]
1789 SymbolLine (X1 Y1 X2 Y2 Thickness)
1794 The endpoints of this line.
1796 The width of this line.
1802 /* x1, y1, x2, y2, thickness */
1803 : T_SYMBOLLINE
'(' measure measure measure measure measure
')'
1805 CreateNewLineInSymbol
(Symbol
, OU
($3), OU
($4), OU
($5), OU
($6), OU
($7));
1809 /* x1, y1, x2, y2, thickness */
1810 : T_SYMBOLLINE
'[' measure measure measure measure measure
']'
1812 CreateNewLineInSymbol
(Symbol
, NU
($3), NU
($4), NU
($5), NU
($6), NU
($7));
1816 /* %start-doc pcbfile Netlist
1820 @ @ @ @dots{} nets @dots{}
1826 pcbnetlist
: pcbnetdef
1830 /* net(...) net(...) ... */
1831 : T_NETLIST
'(' ')' '('
1845 /* %start-doc pcbfile Net
1848 Net ("Name" "Style") (
1849 @ @ @ @dots{} connects @dots{}
1855 The name of this net.
1857 The routing style that should be used when autorouting this net.
1863 /* name style pin pin ... */
1864 : T_NET
'(' STRING STRING
')' '('
1866 Menu
= CreateNewNet
(&yyPCB
->NetlistLib
, $3, $4);
1883 /* %start-doc pcbfile Connect
1891 The name of a pin or pad which is included in this net. Pin and Pad
1892 names are named by the refdes and pin name, like @code{"U14-7"} for
1893 pin 7 of U14, or @code{"T4-E"} for pin E of T4.
1899 : T_CONN
'(' STRING
')'
1901 CreateNewConnection
(Menu
, $3);
1906 /* %start-doc pcbfile Attribute
1909 Attribute ("Name" "Value")
1912 Attributes allow boards and elements to have arbitrary data attached
1913 to them, which is not directly used by PCB itself but may be of use by
1914 other programs or users.
1918 The name of the attribute
1921 The value of the attribute. Values are always stored as strings, even
1922 if the value is interpreted as, for example, a number.
1929 : T_ATTRIBUTE
'(' STRING STRING
')'
1931 CreateNewAttribute
(attr_list
, $3, $4 ?
$4 : (char *)"");
1937 opt_string
: STRING
{ $$
= $1; }
1938 |
/* empty */ { $$
= 0; }
1942 : FLOATING
{ $$
= $1; }
1943 | INTEGER
{ $$
= $1; }
1947 /* Default unit (no suffix) is cmil */
1948 : number
{ do_measure
(&$$
, $1, MIL_TO_COORD
($1) / 100.0, 0); }
1949 | number T_UMIL
{ M
($$
, $1, MIL_TO_COORD
($1) / 100000.0); }
1950 | number T_CMIL
{ M
($$
, $1, MIL_TO_COORD
($1) / 100.0); }
1951 | number T_MIL
{ M
($$
, $1, MIL_TO_COORD
($1)); }
1952 | number T_IN
{ M
($$
, $1, INCH_TO_COORD
($1)); }
1953 | number T_NM
{ M
($$
, $1, MM_TO_COORD
($1) / 1000000.0); }
1954 | number T_PX
{ M
($$
, $1, MM_TO_COORD
($1) / 1000000.0); }
1955 | number T_UM
{ M
($$
, $1, MM_TO_COORD
($1) / 1000.0); }
1956 | number T_MM
{ M
($$
, $1, MM_TO_COORD
($1)); }
1957 | number T_M
{ M
($$
, $1, MM_TO_COORD
($1) * 1000.0); }
1958 | number T_KM
{ M
($$
, $1, MM_TO_COORD
($1) * 1000000.0); }
1963 /* ---------------------------------------------------------------------------
1964 * error routine called by parser library
1966 int yyerror(const char * s
)
1968 Message
(_
("ERROR parsing file '%s'\n"
1970 " description: '%s'\n"),
1971 yyfilename
, yylineno
, s
);
1981 check_file_version
(int ver
)
1983 if
( ver
> PCB_FILE_VERSION
) {
1984 Message
(_
("ERROR: The file you are attempting to load is in a format\n"
1985 "which is too new for this version of pcb. To load this file\n"
1986 "you need a version of pcb which is >= %d. If you are\n"
1987 "using a version built from git source, the source date\n"
1988 "must be >= %d. This copy of pcb can only read files\n"
1989 "up to file version %d.\n"), ver
, ver
, PCB_FILE_VERSION
);
1997 do_measure
(PLMeasure
*m
, Coord i
, double d
, int u
)
2000 m
->bval
= round
(d
);
2006 integer_value
(PLMeasure m
)
2009 yyerror("units ignored here");
2014 old_units
(PLMeasure m
)
2018 return round
(MIL_TO_COORD
(m.ival
));
2022 new_units
(PLMeasure m
)
2026 return round
(MIL_TO_COORD
(m.ival
) / 100.0);