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