1 /*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
5 * Copyright (C) 2012-2021 KiCad Developers, see AUTHORS.txt for contributors.
6 * Copyright (C) 2017 CERN
7 *
8 * @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, you may find one here:
22 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23 * or you may search the http://www.gnu.org website for the version 2 license,
24 * or you may write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
28
29 #ifndef _EAGLE_PARSER_H_
30 #define _EAGLE_PARSER_H_
31
32 #include <map>
33 #include <memory>
34 #include <unordered_map>
35
36 #include <wx/xml/xml.h>
37 #include <wx/string.h>
38 #include <wx/filename.h>
39
40 #include <layer_ids.h>
41 #include <trigo.h>
42 #include <core/wx_stl_compat.h>
43
44 class FOOTPRINT;
45 struct EINSTANCE;
46 struct EPART;
47 struct ETEXT;
48
49 typedef std::unordered_map<wxString, wxXmlNode*> NODE_MAP;
50 typedef std::map<wxString, FOOTPRINT*> FOOTPRINT_MAP;
51 typedef std::map<wxString, EINSTANCE*> EINSTANCE_MAP;
52 typedef std::map<wxString, std::unique_ptr<EPART>> EPART_MAP;
53
54 ///< Translates Eagle special characters to their counterparts in KiCad.
55 wxString escapeName( const wxString& aNetName );
56
getChildrenNodes(NODE_MAP & aMap,const wxString & aName)57 static inline wxXmlNode* getChildrenNodes( NODE_MAP& aMap, const wxString& aName )
58 {
59 auto it = aMap.find( aName );
60 return it == aMap.end() ? nullptr : it->second->GetChildren();
61 }
62
63
64 /**
65 * Implement a simple wrapper around runtime_error to isolate the errors thrown by the
66 * Eagle XML parser.
67 */
68 struct XML_PARSER_ERROR : std::runtime_error
69 {
70 /**
71 * Build an XML error by just calling its parent class constructor, std::runtime_error, with
72 * the passed message.
73 *
74 * @param aMessage is an explanatory error message.
75 */
XML_PARSER_ERRORXML_PARSER_ERROR76 XML_PARSER_ERROR( const wxString& aMessage ) noexcept :
77 std::runtime_error( "XML parser failed - " + aMessage.ToStdString() )
78 {}
79 };
80
81
82 /// segment (element) of our XPATH into the Eagle XML document tree in PTREE form.
83 struct TRIPLET
84 {
85 const char* element;
86 const char* attribute;
87 const char* value;
88
89 TRIPLET( const char* aElement, const char* aAttribute = "", const char* aValue = "" ) :
elementTRIPLET90 element( aElement ),
91 attribute( aAttribute ),
92 value( aValue )
93 {}
94 };
95
96
97 /**
98 * Keep track of what we are working on within a PTREE.
99 *
100 * Then if an exception is thrown, the place within the tree that gave us
101 * grief can be reported almost accurately. To minimally impact
102 * speed, merely assign const char* pointers during the tree walking
103 * expedition. The const char* pointers must be to C strings residing either in
104 * the data or code segment (i.e. "compiled in") or within the XML document, but
105 * not on the stack, since the stack is unwound during the throwing of the
106 * exception. The XML document will not immediately vanish since we capture
107 * the xpath (using function Contents()) before the XML document tree (PTREE)
108 * is destroyed.
109 */
110 class XPATH
111 {
112 std::vector<TRIPLET> p;
113
114 public:
115 void push( const char* aPathSegment, const char* aAttribute="" )
116 {
117 p.emplace_back( aPathSegment, aAttribute );
118 }
119
clear()120 void clear() { p.clear(); }
121
pop()122 void pop() { p.pop_back(); }
123
124 /// modify the last path node's value
Value(const char * aValue)125 void Value( const char* aValue )
126 {
127 p.back().value = aValue;
128 }
129
130 /// modify the last path node's attribute
Attribute(const char * aAttribute)131 void Attribute( const char* aAttribute )
132 {
133 p.back().attribute = aAttribute;
134 }
135
136 /// return the contents of the XPATH as a single string
Contents()137 wxString Contents()
138 {
139 typedef std::vector<TRIPLET>::const_iterator CITER_TRIPLET;
140
141 wxString ret;
142
143 for( CITER_TRIPLET it = p.begin(); it != p.end(); ++it )
144 {
145 if( it != p.begin() )
146 ret += '.';
147
148 ret += it->element;
149
150 if( it->attribute[0] && it->value[0] )
151 {
152 ret += '[';
153 ret += it->attribute;
154 ret += '=';
155 ret += it->value;
156 ret += ']';
157 }
158 }
159
160 return ret;
161 }
162 };
163
164
165 /**
166 * Convert a wxString to a generic type T.
167 *
168 * @param aValue is a wxString containing the value that will be converted to type T.
169 * @throw XML_PARSER_ERROR - an exception is thrown if the parsing fails or if the conversion to
170 * type T is unknown.
171 */
172 template<typename T>
Convert(const wxString & aValue)173 T Convert( const wxString& aValue )
174 {
175 throw XML_PARSER_ERROR( "Conversion failed. Unknown type." );
176 }
177
178 template <>
179 wxString Convert<wxString>( const wxString& aValue );
180
181 /**
182 * Model an optional XML attribute.
183 *
184 * This was implemented as an alternative to OPT. This class should be replaced with a
185 * simple typedef per type using std::optional when C++17 is published.
186 */
187 template <typename T>
188 class OPTIONAL_XML_ATTRIBUTE
189 {
190 private:
191 /// A boolean indicating if the data is present or not.
192 bool m_isAvailable;
193
194 /// The actual data if m_isAvailable is true; otherwise, garbage.
195 T m_data;
196
197 public:
198 /**
199 * Construct a default OPTIONAL_XML_ATTRIBUTE, whose data is not available.
200 */
OPTIONAL_XML_ATTRIBUTE()201 OPTIONAL_XML_ATTRIBUTE() :
202 m_isAvailable( false ),
203 m_data( T() )
204 {}
205
206 /**
207 * @param aData is a wxString containing the value that should be converted to type T. If
208 * aData is empty, the attribute is understood as unavailable; otherwise, the
209 * conversion to T is tried.
210 */
OPTIONAL_XML_ATTRIBUTE(const wxString & aData)211 OPTIONAL_XML_ATTRIBUTE( const wxString& aData )
212 {
213 m_data = T();
214 m_isAvailable = !aData.IsEmpty();
215
216 if( m_isAvailable )
217 Set( aData );
218 }
219
220 /**
221 * @param aData is the value of the XML attribute. If this constructor is called, the
222 * attribute is available.
223 */
224 template<typename V = T>
OPTIONAL_XML_ATTRIBUTE(T aData)225 OPTIONAL_XML_ATTRIBUTE( T aData ) :
226 m_isAvailable( true ),
227 m_data( aData )
228 {}
229
230 /**
231 * @return bool the availability of the attribute.
232 */
233 operator bool() const
234 {
235 return m_isAvailable;
236 }
237
238 /**
239 * Assign to a string (optionally) containing the data.
240 *
241 * @param aData is a wxString that should be converted to T. If the string is empty, the
242 * attribute is set to unavailable.
243 */
244 OPTIONAL_XML_ATTRIBUTE<T>& operator =( const wxString& aData )
245 {
246 m_isAvailable = !aData.IsEmpty();
247
248 if( m_isAvailable )
249 Set( aData );
250
251 return *this;
252 }
253
254 /**
255 * Assign to an object of the base type containing the data.
256 *
257 * @param aData is the actual value of the attribute. Calling this assignment, the attribute
258 * is automatically made available.
259 */
260 OPTIONAL_XML_ATTRIBUTE<T>& operator =( T aData )
261 {
262 m_data = aData;
263 m_isAvailable = true;
264
265 return *this;
266 }
267
268 /**
269 * @param aOther is the object of the base type that should be compared with this one.
270 */
271 bool operator ==( const T& aOther ) const
272 {
273 return m_isAvailable && ( aOther == m_data );
274 }
275
276 /**
277 * Attempt to convert a string to the base type.
278 *
279 * @param aString is the string that will be converted to the base type.
280 */
Set(const wxString & aString)281 void Set( const wxString& aString )
282 {
283 m_data = Convert<T>( aString );
284 m_isAvailable = !aString.IsEmpty();
285 }
286
287 /**
288 * Return a reference to the value of the attribute assuming it is available.
289 *
290 * @return T& - the value of the attribute.
291 */
Get()292 T& Get()
293 {
294 assert( m_isAvailable );
295 return m_data;
296 }
297
298 /**
299 * Return a constant reference to the value of the attribute assuming it is available.
300 *
301 * @return const T& - the value of the attribute.
302 */
CGet()303 const T& CGet() const
304 {
305 assert( m_isAvailable );
306 return m_data;
307 }
308
309 /**
310 * Return a reference to the value of the attribute assuming it is available.
311 *
312 * @return T& - the value of the attribute.
313 */
314 T& operator*()
315 {
316 return Get();
317 }
318
319 /**
320 * Return a constant reference to the value of the attribute assuming it is available.
321 *
322 * @return const T& - the value of the attribute.
323 */
324 const T& operator*() const
325 {
326 return CGet();
327 }
328
329 /**
330 * Return a pointer to the value of the attribute assuming it is available.
331 *
332 * @return T* - the value of the attribute.
333 */
334 T* operator->()
335 {
336 return &Get();
337 }
338
339 /**
340 * Return a constant pointer to the value of the attribute assuming it is available.
341 *
342 * @return const T* - the value of the attribute.
343 */
344 const T* operator->() const
345 {
346 return &CGet();
347 }
348 };
349
350
351 /**
352 * Provide an easy access to the children of an XML node via their names.
353 *
354 * @param currentNode is a pointer to a wxXmlNode, whose children will be mapped.
355 * @return NODE_MAP is a map linking the name of each children to the children itself (via a
356 * wxXmlNode*)
357 */
358 NODE_MAP MapChildren( wxXmlNode* aCurrentNode );
359
360 ///< Convert an Eagle curve end to a KiCad center for S_ARC
361 wxPoint ConvertArcCenter( const wxPoint& aStart, const wxPoint& aEnd, double aAngle );
362
363 // Pre-declare for typedefs
364 struct EROT;
365 struct ECOORD;
366 typedef OPTIONAL_XML_ATTRIBUTE<wxString> opt_wxString;
367 typedef OPTIONAL_XML_ATTRIBUTE<int> opt_int;
368 typedef OPTIONAL_XML_ATTRIBUTE<double> opt_double;
369 typedef OPTIONAL_XML_ATTRIBUTE<bool> opt_bool;
370 typedef OPTIONAL_XML_ATTRIBUTE<EROT> opt_erot;
371 typedef OPTIONAL_XML_ATTRIBUTE<ECOORD> opt_ecoord;
372
373
374 // All of the 'E'STRUCTS below merely hold Eagle XML information verbatim, in binary.
375 // For maintenance and troubleshooting purposes, it was thought that we'd need to
376 // separate the conversion process into distinct steps. There is no intent to have KiCad
377 // forms of information in these 'E'STRUCTS. They are only binary forms
378 // of the Eagle information in the corresponding Eagle XML nodes.
379
380 // Eagle coordinates
381 struct ECOORD
382 {
383 enum EAGLE_UNIT
384 {
385 EU_NM, ///< nanometers
386 EU_MM, ///< millimeters
387 EU_INCH, ///< inches
388 EU_MIL, ///< mils/thous
389 };
390
391 ///< Value expressed in nanometers
392 long long int value;
393
394 ///< Unit used for the value field
395 static constexpr EAGLE_UNIT ECOORD_UNIT = EU_NM;
396
ECOORDECOORD397 ECOORD()
398 : value( 0 )
399 {
400 }
401
ECOORDECOORD402 ECOORD( int aValue, enum EAGLE_UNIT aUnit )
403 : value( ConvertToNm( aValue, aUnit ) )
404 {
405 }
406
407 ECOORD( const wxString& aValue, enum EAGLE_UNIT aUnit );
408
ToMilsECOORD409 int ToMils() const
410 {
411 return value / 25400;
412 }
413
To100NanoMetersECOORD414 int To100NanoMeters() const
415 {
416 return value / 100;
417 }
418
ToNanoMetersECOORD419 int ToNanoMeters() const
420 {
421 return value;
422 }
423
ToMmECOORD424 float ToMm() const
425 {
426 return value / 1000000.0;
427 }
428
ToSchUnitsECOORD429 int ToSchUnits() const { return To100NanoMeters(); }
ToPcbUnitsECOORD430 int ToPcbUnits() const { return ToNanoMeters(); }
431
432 ECOORD operator+( const ECOORD& aOther ) const
433 {
434 return ECOORD( value + aOther.value, ECOORD_UNIT );
435 }
436
437 ECOORD operator-( const ECOORD& aOther ) const
438 {
439 return ECOORD( value - aOther.value, ECOORD_UNIT );
440 }
441
442 bool operator==( const ECOORD& aOther ) const
443 {
444 return value == aOther.value;
445 }
446
447 ///< Converts a size expressed in a certain unit to nanometers.
448 static long long int ConvertToNm( int aValue, enum EAGLE_UNIT aUnit );
449 };
450
451
452 /// Eagle net
453 struct ENET
454 {
455 int netcode;
456 wxString netname;
457
ENETENET458 ENET( int aNetCode, const wxString& aNetName ) :
459 netcode( aNetCode ),
460 netname( aNetName )
461 {}
462
ENETENET463 ENET() :
464 netcode( 0 )
465 {}
466 };
467
468
469 /// Eagle rotation
470 struct EROT
471 {
472 bool mirror;
473 bool spin;
474 double degrees;
475
EROTEROT476 EROT() :
477 mirror( false ),
478 spin( false ),
479 degrees( 0 )
480 {}
481
EROTEROT482 EROT( double aDegrees ) :
483 mirror( false ),
484 spin( false ),
485 degrees( aDegrees )
486 {}
487 };
488
489
490 /// Eagle wire
491 struct EWIRE
492 {
493 ECOORD x1;
494 ECOORD y1;
495 ECOORD x2;
496 ECOORD y2;
497 ECOORD width;
498 LAYER_NUM layer;
499
500 // for style: (continuous | longdash | shortdash | dashdot)
501 enum {
502 CONTINUOUS,
503 LONGDASH,
504 SHORTDASH,
505 DASHDOT,
506 };
507 opt_int style;
508 opt_double curve; ///< range is -359.9..359.9
509
510 // for cap: (flat | round)
511 enum {
512 FLAT,
513 ROUND,
514 };
515 opt_int cap;
516
517 EWIRE( wxXmlNode* aWire );
518 };
519
520
521 /// Eagle Junction
522 struct EJUNCTION
523 {
524 ECOORD x;
525 ECOORD y;
526
527 EJUNCTION( wxXmlNode* aJunction);
528 };
529
530
531 /// Eagle label
532 struct ELABEL
533 {
534 ECOORD x;
535 ECOORD y;
536 ECOORD size;
537 LAYER_NUM layer;
538 opt_erot rot;
539 opt_wxString xref;
540 wxString netname;
541
542 ELABEL( wxXmlNode* aLabel, const wxString& aNetName );
543 };
544
545
546 /// Eagle via
547 struct EVIA
548 {
549 ECOORD x;
550 ECOORD y;
551 int layer_front_most; /// < extent
552 int layer_back_most; /// < inclusive
553 ECOORD drill;
554 opt_ecoord diam;
555 opt_wxString shape;
556
557 EVIA( wxXmlNode* aVia );
558 };
559
560
561 /// Eagle circle
562 struct ECIRCLE
563 {
564 ECOORD x;
565 ECOORD y;
566 ECOORD radius;
567 ECOORD width;
568 LAYER_NUM layer;
569
570 ECIRCLE( wxXmlNode* aCircle );
571 };
572
573
574 /// Eagle XML rectangle in binary
575 struct ERECT
576 {
577 ECOORD x1;
578 ECOORD y1;
579 ECOORD x2;
580 ECOORD y2;
581 int layer;
582 opt_erot rot;
583
584 ERECT( wxXmlNode* aRect );
585 };
586
587
588 /**
589 * Parse an Eagle "attribute" XML element.
590 *
591 * @note An attribute element is different than an XML element attribute. The attribute element
592 * is a full XML node in and of itself, and has attributes of its own. Blame Eagle.
593 */
594 struct EATTR
595 {
596 wxString name;
597 opt_wxString value;
598 opt_ecoord x;
599 opt_ecoord y;
600 opt_ecoord size;
601 opt_int layer;
602 opt_double ratio;
603 opt_erot rot;
604
605 enum { // for 'display'
606 Off,
607 VALUE,
608 NAME,
609 BOTH,
610 };
611 opt_int display;
612 opt_int align;
613
614 EATTR( wxXmlNode* aTree );
EATTREATTR615 EATTR() {}
616 };
617
618
619 /// Eagle dimension element
620 struct EDIMENSION
621 {
622 ECOORD x1;
623 ECOORD y1;
624 ECOORD x2;
625 ECOORD y2;
626 ECOORD x3;
627 ECOORD y3;
628 int layer;
629
630 opt_wxString dimensionType;
631
632 EDIMENSION( wxXmlNode* aDimension );
633 };
634
635
636 /// Eagle text element
637 struct ETEXT
638 {
639 wxString text;
640 ECOORD x;
641 ECOORD y;
642 ECOORD size;
643 int layer;
644 opt_wxString font;
645 opt_double ratio;
646 opt_erot rot;
647
648 enum { // for align
649 CENTER = 0,
650 CENTER_LEFT,
651 TOP_CENTER,
652 TOP_LEFT,
653 TOP_RIGHT,
654
655 // opposites are -1 x above, used by code tricks in here
656 CENTER_RIGHT = -CENTER_LEFT,
657 BOTTOM_CENTER = -TOP_CENTER,
658 BOTTOM_LEFT = -TOP_RIGHT,
659 BOTTOM_RIGHT = -TOP_LEFT,
660 };
661
662 opt_int align;
663
664 ETEXT( wxXmlNode* aText );
665
666 /// Calculate text size based on font type and size
667 wxSize ConvertSize() const;
668 };
669
670
671 /**
672 * Parse an Eagle frame element.
673 */
674 struct EFRAME
675 {
676 ECOORD x1;
677 ECOORD y1;
678 ECOORD x2;
679 ECOORD y2;
680 int columns;
681 int rows;
682 int layer;
683 opt_bool border_left;
684 opt_bool border_top;
685 opt_bool border_right;
686 opt_bool border_bottom;
687
688 EFRAME( wxXmlNode* aFrameNode );
689 };
690
691
692 /// Structure holding common properties for through-hole and SMD pads
693 struct EPAD_COMMON
694 {
695 wxString name;
696 ECOORD x, y;
697 opt_erot rot;
698 opt_bool stop;
699 opt_bool thermals;
700
701 EPAD_COMMON( wxXmlNode* aPad );
702 };
703
704
705 /// Eagle thru hole pad
706 struct EPAD : public EPAD_COMMON
707 {
708 ECOORD drill;
709 opt_ecoord diameter;
710
711 // for shape: (square | round | octagon | long | offset)
712 enum {
713 UNDEF = -1,
714 SQUARE,
715 ROUND,
716 OCTAGON,
717 LONG,
718 OFFSET,
719 };
720 opt_int shape;
721 opt_bool first;
722
723 EPAD( wxXmlNode* aPad );
724 };
725
726
727 /// Eagle SMD pad
728 struct ESMD : public EPAD_COMMON
729 {
730 ECOORD dx;
731 ECOORD dy;
732 int layer;
733 opt_int roundness;
734 opt_bool cream;
735
736 ESMD( wxXmlNode* aSMD );
737 };
738
739
740 /// Eagle pin element
741 struct EPIN
742 {
743 wxString name;
744 ECOORD x;
745 ECOORD y;
746
747 opt_wxString visible;
748 opt_wxString length;
749 opt_wxString direction;
750 opt_wxString function;
751 opt_int swaplevel;
752 opt_erot rot;
753
754 EPIN( wxXmlNode* aPin );
755 };
756
757
758 /// Eagle vertex
759 struct EVERTEX
760 {
761 ECOORD x;
762 ECOORD y;
763 opt_double curve; ///< range is -359.9..359.9
764
765 EVERTEX( wxXmlNode* aVertex );
766 };
767
768
769 /// Eagle polygon, without vertices which are parsed as needed
770 struct EPOLYGON
771 {
772 ECOORD width;
773 int layer;
774 opt_ecoord spacing;
775
776 // KiCad priority is opposite of Eagle rank, that is:
777 // - Eagle Low rank drawn first
778 // - KiCad high priority drawn first
779 // So since Eagle has an upper limit we define this, used for the cases
780 // where no rank is specified.
781 static const int max_priority = 6;
782
783 enum { // for pour
784 SOLID,
785 HATCH,
786 CUTOUT,
787 };
788 int pour;
789 opt_ecoord isolate;
790 opt_bool orphans;
791 opt_bool thermals;
792 opt_int rank;
793
794 EPOLYGON( wxXmlNode* aPolygon );
795 };
796
797
798 /// Eagle hole element
799 struct EHOLE
800 {
801 ECOORD x;
802 ECOORD y;
803 ECOORD drill;
804
805 EHOLE( wxXmlNode* aHole );
806 };
807
808
809 /// Eagle element element
810 struct EELEMENT
811 {
812 wxString name;
813 wxString library;
814 wxString package;
815 wxString value;
816 ECOORD x;
817 ECOORD y;
818 opt_bool locked;
819 opt_bool smashed;
820 opt_erot rot;
821
822 EELEMENT( wxXmlNode* aElement );
823 };
824
825
826 struct ELAYER
827 {
828 int number;
829 wxString name;
830 int color;
831 int fill;
832 opt_bool visible;
833 opt_bool active;
834
835 ELAYER( wxXmlNode* aLayer );
836 };
837
838
839 struct EAGLE_LAYER
840 {
841 enum
842 {
843 TOP = 1,
844 ROUTE2 = 2,
845 ROUTE3 = 3,
846 ROUTE4 = 4,
847 ROUTE5 = 5,
848 ROUTE6 = 6,
849 ROUTE7 = 7,
850 ROUTE8 = 8,
851 ROUTE9 = 9,
852 ROUTE10 = 10,
853 ROUTE11 = 11,
854 ROUTE12 = 12,
855 ROUTE13 = 13,
856 ROUTE14 = 14,
857 ROUTE15 = 15,
858 BOTTOM = 16,
859 PADS = 17,
860 VIAS = 18,
861 UNROUTED = 19,
862 DIMENSION = 20,
863 TPLACE = 21,
864 BPLACE = 22,
865 TORIGINS = 23,
866 BORIGINS = 24,
867 TNAMES = 25,
868 BNAMES = 26,
869 TVALUES = 27,
870 BVALUES = 28,
871 TSTOP = 29,
872 BSTOP = 30,
873 TCREAM = 31,
874 BCREAM = 32,
875 TFINISH = 33,
876 BFINISH = 34,
877 TGLUE = 35,
878 BGLUE = 36,
879 TTEST = 37,
880 BTEST = 38,
881 TKEEPOUT = 39,
882 BKEEPOUT = 40,
883 TRESTRICT = 41,
884 BRESTRICT = 42,
885 VRESTRICT = 43,
886 DRILLS = 44,
887 HOLES = 45,
888 MILLING = 46,
889 MEASURES = 47,
890 DOCUMENT = 48,
891 REFERENCELC = 49,
892 REFERENCELS = 50,
893 TDOCU = 51,
894 BDOCU = 52,
895 NETS = 91,
896 BUSSES = 92,
897 PINS = 93,
898 SYMBOLS = 94,
899 NAMES = 95,
900 VALUES = 96,
901 INFO = 97,
902 GUIDE = 98,
903 USERLAYER1 = 160,
904 USERLAYER2 = 161
905 };
906 };
907
908
909 struct EPART
910 {
911 /*
912 * <!ELEMENT part (attribute*, variant*)>
913 * <!ATTLIST part
914 * name %String; #REQUIRED
915 * library %String; #REQUIRED
916 * deviceset %String; #REQUIRED
917 * device %String; #REQUIRED
918 * technology %String; ""
919 * value %String; #IMPLIED
920 * >
921 */
922
923 wxString name;
924 wxString library;
925 wxString deviceset;
926 wxString device;
927 opt_wxString technology;
928 opt_wxString value;
929 std::map<std::string,std::string> attribute;
930 std::map<std::string,std::string> variant;
931
932 EPART( wxXmlNode* aPart );
933 };
934
935
936 struct EINSTANCE
937 {
938 /*
939 * <!ELEMENT instance (attribute)*>
940 * <!ATTLIST instance
941 * part %String; #REQUIRED
942 * gate %String; #REQUIRED
943 * x %Coord; #REQUIRED
944 * y %Coord; #REQUIRED
945 * smashed %Bool; "no"
946 * rot %Rotation; "R0"
947 * >
948 */
949
950 wxString part;
951 wxString gate;
952 ECOORD x;
953 ECOORD y;
954 opt_bool smashed;
955 opt_erot rot;
956
957 EINSTANCE( wxXmlNode* aInstance );
958 };
959
960
961 struct EGATE
962 {
963 /*
964 * <!ELEMENT gate EMPTY>
965 * <!ATTLIST gate
966 * name %String; #REQUIRED
967 * symbol %String; #REQUIRED
968 * x %Coord; #REQUIRED
969 * y %Coord; #REQUIRED
970 * addlevel %GateAddLevel; "next"
971 * swaplevel %Int; "0"
972 * >
973 */
974
975 wxString name;
976 wxString symbol;
977
978 ECOORD x;
979 ECOORD y;
980
981 opt_int addlevel;
982 opt_int swaplevel;
983
984 enum
985 {
986 MUST,
987 CAN,
988 NEXT,
989 REQUEST,
990 ALWAYS
991 };
992
993 EGATE( wxXmlNode* aGate );
994 };
995
996
997 struct ECONNECT
998 {
999 /*
1000 * <!ELEMENT connect EMPTY>
1001 * <!ATTLIST connect
1002 * gate %String; #REQUIRED
1003 * pin %String; #REQUIRED
1004 * pad %String; #REQUIRED
1005 * route %ContactRoute; "all"
1006 * >
1007 */
1008 wxString gate;
1009 wxString pin;
1010 wxString pad;
1011 //int contactroute; // TODO
1012
1013 ECONNECT( wxXmlNode* aConnect );
1014 };
1015
1016
1017 struct EDEVICE
1018 {
1019 /*
1020 * <!ELEMENT device (connects?, technologies?)>
1021 * <!ATTLIST device
1022 * name %String; ""
1023 * package %String; #IMPLIED
1024 * >
1025 */
1026 wxString name;
1027 opt_wxString package;
1028
1029 std::vector<ECONNECT> connects;
1030
1031 EDEVICE( wxXmlNode* aDevice );
1032 };
1033
1034
1035 struct EDEVICE_SET
1036 {
1037 /*
1038 <!ELEMENT deviceset (description?, gates, devices)>
1039 <!ATTLIST deviceset
1040 name %String; #REQUIRED
1041 prefix %String; ""
1042 uservalue %Bool; "no"
1043 >
1044 */
1045
1046 wxString name;
1047 opt_wxString prefix;
1048 opt_bool uservalue;
1049 //std::vector<EDEVICE> devices;
1050 //std::vector<EGATE> gates;
1051
1052
1053 EDEVICE_SET( wxXmlNode* aDeviceSet );
1054 };
1055
1056
1057 struct ECLASS
1058 {
1059 wxString number;
1060 wxString name;
1061 std::map<wxString, ECOORD> clearanceMap;
1062
1063 ECLASS( wxXmlNode* aClass );
1064 };
1065
1066
1067 #endif // _EAGLE_PARSER_H_
1068