You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							4002 lines
						
					
					
						
							101 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							4002 lines
						
					
					
						
							101 KiB
						
					
					
				
								/*
							 | 
						|
								 * This program source code file is part of KiCad, a free EDA CAD application.
							 | 
						|
								 *
							 | 
						|
								 * Copyright (C) 2007-2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
							 | 
						|
								 * Copyright (C) 2007-2015 KiCad Developers, see change_log.txt for contributors.
							 | 
						|
								 *
							 | 
						|
								 * This program is free software; you can redistribute it and/or
							 | 
						|
								 * modify it under the terms of the GNU General Public License
							 | 
						|
								 * as published by the Free Software Foundation; either version 2
							 | 
						|
								 * of the License, or (at your option) any later version.
							 | 
						|
								 *
							 | 
						|
								 * This program is distributed in the hope that it will be useful,
							 | 
						|
								 * but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						|
								 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
							 | 
						|
								 * GNU General Public License for more details.
							 | 
						|
								 *
							 | 
						|
								 * You should have received a copy of the GNU General Public License
							 | 
						|
								 * along with this program; if not, you may find one here:
							 | 
						|
								 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
							 | 
						|
								 * or you may search the http://www.gnu.org website for the version 2 license,
							 | 
						|
								 * or you may write to the Free Software Foundation, Inc.,
							 | 
						|
								 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								#ifndef SPECCTRA_H_
							 | 
						|
								#define SPECCTRA_H_
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								//  see http://www.boost.org/libs/ptr_container/doc/ptr_sequence_adapter.html
							 | 
						|
								#include <boost/ptr_container/ptr_vector.hpp>
							 | 
						|
								
							 | 
						|
								//  see http://www.boost.org/libs/ptr_container/doc/ptr_set.html
							 | 
						|
								#include <boost/ptr_container/ptr_set.hpp>
							 | 
						|
								#include <boost/shared_ptr.hpp>
							 | 
						|
								
							 | 
						|
								#include <fctsys.h>
							 | 
						|
								#include <specctra_lexer.h>
							 | 
						|
								#include <pcbnew.h>
							 | 
						|
								
							 | 
						|
								// all outside the DSN namespace:
							 | 
						|
								class BOARD;
							 | 
						|
								class TRACK;
							 | 
						|
								class VIA;
							 | 
						|
								class NETCLASS;
							 | 
						|
								class MODULE;
							 | 
						|
								class SHAPE_POLY_SET;
							 | 
						|
								
							 | 
						|
								typedef DSN::T  DSN_T;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								    This source file implements export and import capabilities to the
							 | 
						|
								    specctra dsn file format.  The grammar for that file format is documented
							 | 
						|
								    fairly well.  There are classes for each major type of descriptor in the
							 | 
						|
								    spec.
							 | 
						|
								
							 | 
						|
								    Since there are so many classes in here, it may be helpful to generate
							 | 
						|
								    the Doxygen directory:
							 | 
						|
								
							 | 
						|
								    $ cd <kicadSourceRoot>
							 | 
						|
								    $ doxygen
							 | 
						|
								
							 | 
						|
								    Then you can view the html documentation in the <kicadSourceRoot>/doxygen
							 | 
						|
								    directory.  The main class in this file is SPECCTRA_DB and its main
							 | 
						|
								    functions are LoadPCB(), LoadSESSION(), and ExportPCB().
							 | 
						|
								
							 | 
						|
								    Wide use is made of boost::ptr_vector<> and std::vector<> template classes.
							 | 
						|
								    If the contained object is small, then std::vector tends to be used.
							 | 
						|
								    If the contained object is large, variable size, or would require writing
							 | 
						|
								    an assignment operator() or copy constructore, then boost::ptr_vector
							 | 
						|
								    cannot be beat.
							 | 
						|
								*/
							 | 
						|
								namespace DSN {
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Function GetTokenText
							 | 
						|
								 * is in the DSN namespace and returns the C string representing a
							 | 
						|
								 * SPECCTRA_DB::keyword.  We needed a non-instanance function to get at
							 | 
						|
								 * the SPECCTRA_DB::keyword[] and class SPECCTRA_DB is not defined yet.
							 | 
						|
								 */
							 | 
						|
								const char* GetTokenText( T aTok );
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Struct POINT
							 | 
						|
								 * is a holder for a point in the SPECCTRA DSN coordinate system.  It can also
							 | 
						|
								 * be used to hold a distance (vector really) from some origin.
							 | 
						|
								 */
							 | 
						|
								struct POINT
							 | 
						|
								{
							 | 
						|
								    double  x;
							 | 
						|
								    double  y;
							 | 
						|
								
							 | 
						|
								    POINT() { x=0.0; y=0.0; }
							 | 
						|
								
							 | 
						|
								    POINT( double aX, double aY ) :
							 | 
						|
								        x(aX), y(aY)
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    bool operator==( const POINT& other ) const
							 | 
						|
								    {
							 | 
						|
								        return x==other.x && y==other.y;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    bool operator!=( const POINT& other ) const
							 | 
						|
								    {
							 | 
						|
								        return !( *this == other );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    POINT& operator+=( const POINT& other )
							 | 
						|
								    {
							 | 
						|
								        x += other.x;
							 | 
						|
								        y += other.y;
							 | 
						|
								        return *this;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    POINT& operator=( const POINT& other )
							 | 
						|
								    {
							 | 
						|
								        x = other.x;
							 | 
						|
								        y = other.y;
							 | 
						|
								        return *this;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function FixNegativeZero
							 | 
						|
								     * will change negative zero to positive zero in the IEEE floating point
							 | 
						|
								     * storage format.  Basically turns off the sign bit if the mantissa and
							 | 
						|
								     * exponent say the value is otherwise zero.
							 | 
						|
								     */
							 | 
						|
								    void FixNegativeZero()
							 | 
						|
								    {
							 | 
						|
								        if( x == -0.0 )
							 | 
						|
								            x = 0.0;
							 | 
						|
								        if( y == -0.0 )
							 | 
						|
								            y = 0.0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function Format
							 | 
						|
								     * writes this object as ASCII out to an OUTPUTFORMATTER according to the
							 | 
						|
								     * SPECCTRA DSN format.
							 | 
						|
								     * @param out The formatter to write to.
							 | 
						|
								     * @param nestLevel A multiple of the number of spaces to preceed the output with.
							 | 
						|
								     * @throw IO_ERROR if a system error writing the output, such as a full disk.
							 | 
						|
								     */
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        out->Print( nestLevel, " %.6g %.6g", x, y );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								typedef std::vector<std::string>    STRINGS;
							 | 
						|
								typedef std::vector<POINT>          POINTS;
							 | 
						|
								
							 | 
						|
								struct PROPERTY
							 | 
						|
								{
							 | 
						|
								    std::string name;
							 | 
						|
								    std::string value;
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function Format
							 | 
						|
								     * writes this object as ASCII out to an OUTPUTFORMATTER according to the
							 | 
						|
								     * SPECCTRA DSN format.
							 | 
						|
								     * @param out The formatter to write to.
							 | 
						|
								     * @param nestLevel A multiple of the number of spaces to preceed the output with.
							 | 
						|
								     * @throw IO_ERROR if a system error writing the output, such as a full disk.
							 | 
						|
								     */
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quoteName  = out->GetQuoteChar( name.c_str() );
							 | 
						|
								        const char* quoteValue = out->GetQuoteChar( value.c_str() );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, "(%s%s%s %s%s%s)\n",
							 | 
						|
								                   quoteName,  name.c_str(), quoteName,
							 | 
						|
								                   quoteValue, value.c_str(), quoteValue );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef std::vector<PROPERTY>       PROPERTIES;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class UNIT_RES;
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class ELEM
							 | 
						|
								 * is a base class for any DSN element class.
							 | 
						|
								 * See class ELEM_HOLDER also.
							 | 
						|
								 */
							 | 
						|
								class ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								protected:
							 | 
						|
								    DSN_T           type;
							 | 
						|
								    ELEM*           parent;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function makeHash
							 | 
						|
								     * returns a string which uniquely represents this ELEM amoung other
							 | 
						|
								     * ELEMs of the same derived class as "this" one.
							 | 
						|
								     * It is not useable for all derived classes, only those which plan for
							 | 
						|
								     * it by implementing a FormatContents() function that captures all info
							 | 
						|
								     * which will be used in the subsequent string compare.  THIS SHOULD
							 | 
						|
								     * NORMALLY EXCLUDE THE TYPENAME, AND INSTANCE NAME OR ID AS WELL.
							 | 
						|
								     */
							 | 
						|
								    std::string makeHash()
							 | 
						|
								    {
							 | 
						|
								        sf.Clear();
							 | 
						|
								        FormatContents( &sf, 0 );
							 | 
						|
								        sf.StripUseless();
							 | 
						|
								
							 | 
						|
								        return sf.GetString();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // avoid creating this for every compare, make static.
							 | 
						|
								    static STRING_FORMATTER  sf;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    ELEM( DSN_T aType, ELEM* aParent = 0 );
							 | 
						|
								
							 | 
						|
								    virtual ~ELEM();
							 | 
						|
								
							 | 
						|
								    DSN_T   Type() const { return type; }
							 | 
						|
								
							 | 
						|
								    const char* Name() const;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function GetUnits
							 | 
						|
								     * returns the units for this section.  Derived classes may override this
							 | 
						|
								     * to check for section specific overrides.
							 | 
						|
								     * @return UNIT_RES* - from a local or parent scope
							 | 
						|
								     */
							 | 
						|
								    virtual UNIT_RES* GetUnits() const;
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function Format
							 | 
						|
								     * writes this object as ASCII out to an OUTPUTFORMATTER according to the
							 | 
						|
								     * SPECCTRA DSN format.
							 | 
						|
								     * @param out The formatter to write to.
							 | 
						|
								     * @param nestLevel A multiple of the number of spaces to preceed the output with.
							 | 
						|
								     * @throw IO_ERROR if a system error writing the output, such as a full disk.
							 | 
						|
								     */
							 | 
						|
								    virtual void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR );
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function FormatContents
							 | 
						|
								     * writes the contents as ASCII out to an OUTPUTFORMATTER according to the
							 | 
						|
								     * SPECCTRA DSN format.  This is the same as Format() except that the outer
							 | 
						|
								     * wrapper is not included.
							 | 
						|
								     * @param out The formatter to write to.
							 | 
						|
								     * @param nestLevel A multiple of the number of spaces to preceed the output with.
							 | 
						|
								     * @throw IO_ERROR if a system error writing the output, such as a full disk.
							 | 
						|
								     */
							 | 
						|
								    virtual void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        // overridden in ELEM_HOLDER
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetParent( ELEM* aParent )
							 | 
						|
								    {
							 | 
						|
								        parent = aParent;
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class ELEM_HOLDER
							 | 
						|
								 * is a holder for any DSN class.  It can contain other
							 | 
						|
								 * class instances, including classes derived from this class.
							 | 
						|
								 */
							 | 
						|
								class ELEM_HOLDER : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    typedef boost::ptr_vector<ELEM> ELEM_ARRAY;
							 | 
						|
								
							 | 
						|
								    ELEM_ARRAY      kids;      ///< ELEM pointers
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    ELEM_HOLDER( DSN_T aType, ELEM* aParent = 0 ) :
							 | 
						|
								        ELEM( aType, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    virtual void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR );
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    //-----< list operations >--------------------------------------------
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function FindElem
							 | 
						|
								     * finds a particular instance number of a given type of ELEM.
							 | 
						|
								     * @param aType The type of ELEM to find
							 | 
						|
								     * @param instanceNum The instance number of to find: 0 for first, 1 for second, etc.
							 | 
						|
								     * @return int - The index into the kids array or -1 if not found.
							 | 
						|
								     */
							 | 
						|
								    int FindElem( DSN_T aType, int instanceNum = 0 );
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function Length
							 | 
						|
								     * returns the number of ELEMs in this ELEM.
							 | 
						|
								     * @return int - the count of children
							 | 
						|
								     */
							 | 
						|
								    int     Length() const
							 | 
						|
								    {
							 | 
						|
								        return kids.size();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void    Append( ELEM* aElem )
							 | 
						|
								    {
							 | 
						|
								        kids.push_back( aElem );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ELEM*   Replace( int aIndex, ELEM* aElem )
							 | 
						|
								    {
							 | 
						|
								        ELEM_ARRAY::auto_type ret = kids.replace( aIndex, aElem );
							 | 
						|
								        return ret.release();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ELEM*   Remove( int aIndex )
							 | 
						|
								    {
							 | 
						|
								        ELEM_ARRAY::auto_type ret = kids.release( kids.begin()+aIndex );
							 | 
						|
								        return ret.release();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void    Insert( int aIndex, ELEM* aElem )
							 | 
						|
								    {
							 | 
						|
								        kids.insert( kids.begin()+aIndex, aElem );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ELEM*   At( int aIndex ) const
							 | 
						|
								    {
							 | 
						|
								        // we have varying sized objects and are using polymorphism, so we
							 | 
						|
								        // must return a pointer not a reference.
							 | 
						|
								        return (ELEM*) &kids[aIndex];
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ELEM* operator[]( int aIndex ) const
							 | 
						|
								    {
							 | 
						|
								        return At( aIndex );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void    Delete( int aIndex )
							 | 
						|
								    {
							 | 
						|
								        kids.erase( kids.begin()+aIndex );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class PARSER
							 | 
						|
								 * is simply a configuration record per the SPECCTRA DSN file spec.
							 | 
						|
								 * It is not actually a parser, but rather corresponds to <parser_descriptor>
							 | 
						|
								 */
							 | 
						|
								class PARSER : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    char        string_quote;
							 | 
						|
								    bool        space_in_quoted_tokens;
							 | 
						|
								    bool        case_sensitive;
							 | 
						|
								    bool        wires_include_testpoint;
							 | 
						|
								    bool        routes_include_testpoint;
							 | 
						|
								    bool        routes_include_guides;
							 | 
						|
								    bool        routes_include_image_conductor;
							 | 
						|
								    bool        via_rotate_first;
							 | 
						|
								    bool        generated_by_freeroute;
							 | 
						|
								
							 | 
						|
								    /// This holds pairs of strings, one pair for each constant definition
							 | 
						|
								    STRINGS     constants;
							 | 
						|
								
							 | 
						|
								    std::string host_cad;
							 | 
						|
								    std::string host_version;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    PARSER( ELEM* aParent );
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR );
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class UNIT_RES
							 | 
						|
								 * is a holder for either a T_unit or T_resolution object which are usually
							 | 
						|
								 * mutually exclusive in the dsn grammar, except within the T_pcb level.
							 | 
						|
								 */
							 | 
						|
								class UNIT_RES : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    DSN_T       units;
							 | 
						|
								    int         value;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * A static instance which holds the default units of T_inch and 2540000.
							 | 
						|
								     * See page 108 of the specctra spec, May 2000.
							 | 
						|
								     */
							 | 
						|
								    static UNIT_RES Default;
							 | 
						|
								
							 | 
						|
								    UNIT_RES( ELEM* aParent, DSN_T aType ) :
							 | 
						|
								        ELEM( aType, aParent )
							 | 
						|
								    {
							 | 
						|
								        units = T_inch;
							 | 
						|
								        value = 2540000;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    DSN_T   GetEngUnits() const  { return units; }
							 | 
						|
								    int     GetValue() const  { return value; }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        if( type == T_unit )
							 | 
						|
								            out->Print( nestLevel, "(%s %s)\n", Name(),
							 | 
						|
								                       GetTokenText(units) );
							 | 
						|
								
							 | 
						|
								        else    // T_resolution
							 | 
						|
								            out->Print( nestLevel, "(%s %s %d)\n", Name(),
							 | 
						|
								                       GetTokenText(units), value );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class RECTANGLE : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     layer_id;
							 | 
						|
								
							 | 
						|
								    POINT           point0;         ///< one of two opposite corners
							 | 
						|
								    POINT           point1;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    RECTANGLE( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_rect, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetLayerId( const char* aLayerId )
							 | 
						|
								    {
							 | 
						|
								        layer_id = aLayerId;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetCorners( const POINT& aPoint0, const POINT& aPoint1 )
							 | 
						|
								    {
							 | 
						|
								        point0 = aPoint0;
							 | 
						|
								        point0.FixNegativeZero();
							 | 
						|
								
							 | 
						|
								        point1 = aPoint1;
							 | 
						|
								        point1.FixNegativeZero();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    POINT GetOrigin() { return point0; }
							 | 
						|
								    POINT GetEnd() { return point1; }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* newline = nestLevel ? "\n" : "";
							 | 
						|
								
							 | 
						|
								        const char* quote = out->GetQuoteChar( layer_id.c_str() );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, "(%s %s%s%s %.6g %.6g %.6g %.6g)%s",
							 | 
						|
								                   Name(),
							 | 
						|
								                   quote, layer_id.c_str(), quote,
							 | 
						|
								                   point0.x, point0.y,
							 | 
						|
								                   point1.x, point1.y,
							 | 
						|
								                   newline );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class RULE
							 | 
						|
								 * corresponds to the <rule_descriptor> in the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								class RULE : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    STRINGS     rules;      ///< rules are saved in std::string form.
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    RULE( ELEM* aParent, DSN_T aType ) :
							 | 
						|
								        ELEM( aType, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        out->Print( nestLevel, "(%s", Name() );
							 | 
						|
								
							 | 
						|
								        bool singleLine;
							 | 
						|
								
							 | 
						|
								        if( rules.size() == 1 )
							 | 
						|
								        {
							 | 
						|
								            singleLine = true;
							 | 
						|
								            out->Print( 0, " %s)", rules.begin()->c_str() );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        else
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "\n" );
							 | 
						|
								            singleLine = false;
							 | 
						|
								            for( STRINGS::const_iterator i = rules.begin();  i!=rules.end(); ++i )
							 | 
						|
								                out->Print( nestLevel+1, "%s\n", i->c_str() );
							 | 
						|
								            out->Print( nestLevel, ")" );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( nestLevel || !singleLine )
							 | 
						|
								            out->Print( 0, "\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class LAYER_RULE : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    STRINGS         layer_ids;
							 | 
						|
								    RULE*           rule;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    LAYER_RULE( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_layer_rule, aParent )
							 | 
						|
								    {
							 | 
						|
								        rule = 0;
							 | 
						|
								    }
							 | 
						|
								    ~LAYER_RULE()
							 | 
						|
								    {
							 | 
						|
								        delete rule;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        out->Print( nestLevel, "(%s", Name() );
							 | 
						|
								
							 | 
						|
								        for( STRINGS::const_iterator i=layer_ids.begin();  i!=layer_ids.end();  ++i )
							 | 
						|
								        {
							 | 
						|
								            const char* quote = out->GetQuoteChar( i->c_str() );
							 | 
						|
								            out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								        out->Print( 0 , "\n" );
							 | 
						|
								
							 | 
						|
								        if( rule )
							 | 
						|
								            rule->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<LAYER_RULE>   LAYER_RULES;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class PATH
							 | 
						|
								 * supports both the <path_descriptor> and the <polygon_descriptor> per
							 | 
						|
								 * the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								class PATH : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     layer_id;
							 | 
						|
								    double          aperture_width;
							 | 
						|
								
							 | 
						|
								    POINTS          points;
							 | 
						|
								    DSN_T           aperture_type;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    PATH( ELEM* aParent, DSN_T aType = T_path ) :
							 | 
						|
								        ELEM( aType, aParent )
							 | 
						|
								    {
							 | 
						|
								        aperture_width = 0.0;
							 | 
						|
								        aperture_type  = T_round;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void AppendPoint( const POINT& aPoint )
							 | 
						|
								    {
							 | 
						|
								        points.push_back( aPoint );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    POINTS& GetPoints() {return points; }
							 | 
						|
								
							 | 
						|
								    void SetLayerId( const char* aLayerId )
							 | 
						|
								    {
							 | 
						|
								        layer_id = aLayerId;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetAperture( double aWidth )
							 | 
						|
								    {
							 | 
						|
								        aperture_width = aWidth;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* newline = nestLevel ? "\n" : "";
							 | 
						|
								
							 | 
						|
								        const char* quote = out->GetQuoteChar( layer_id.c_str() );
							 | 
						|
								
							 | 
						|
								        const int RIGHTMARGIN = 70;
							 | 
						|
								        int perLine = out->Print( nestLevel, "(%s %s%s%s %.6g",
							 | 
						|
								                               Name(),
							 | 
						|
								                               quote, layer_id.c_str(), quote,
							 | 
						|
								                               aperture_width );
							 | 
						|
								
							 | 
						|
								        int wrapNest = std::max( nestLevel+1, 6 );
							 | 
						|
								        for( unsigned i=0;  i<points.size();  ++i )
							 | 
						|
								        {
							 | 
						|
								            if( perLine > RIGHTMARGIN )
							 | 
						|
								            {
							 | 
						|
								                out->Print( 0, "\n" );
							 | 
						|
								                perLine = out->Print( wrapNest, "%s", "" );
							 | 
						|
								            }
							 | 
						|
								            else
							 | 
						|
								                perLine += out->Print( 0, "  " );
							 | 
						|
								
							 | 
						|
								            perLine += out->Print( 0, "%.6g %.6g", points[i].x, points[i].y );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( aperture_type == T_square )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "(aperture_type square)" );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        out->Print( 0, ")%s", newline );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<PATH> PATHS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class BOUNDARY : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    // only one or the other of these two is used, not both
							 | 
						|
								    PATHS           paths;
							 | 
						|
								    RECTANGLE*      rectangle;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    BOUNDARY( ELEM* aParent, DSN_T aType = T_boundary ) :
							 | 
						|
								        ELEM( aType, aParent )
							 | 
						|
								    {
							 | 
						|
								        rectangle = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~BOUNDARY()
							 | 
						|
								    {
							 | 
						|
								        delete rectangle;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * GetCorners fills aBuffer with a list of coordinates (x,y) of corners
							 | 
						|
								     */
							 | 
						|
								    void GetCorners( std::vector<double>& aBuffer )
							 | 
						|
								    {
							 | 
						|
								        if( rectangle )
							 | 
						|
								        {
							 | 
						|
								            aBuffer.push_back( rectangle->GetOrigin().x );
							 | 
						|
								            aBuffer.push_back( rectangle->GetOrigin().y );
							 | 
						|
								
							 | 
						|
								            aBuffer.push_back( rectangle->GetOrigin().x );
							 | 
						|
								            aBuffer.push_back( rectangle->GetEnd().y );
							 | 
						|
								
							 | 
						|
								            aBuffer.push_back( rectangle->GetEnd().x );
							 | 
						|
								            aBuffer.push_back( rectangle->GetEnd().y );
							 | 
						|
								
							 | 
						|
								            aBuffer.push_back( rectangle->GetEnd().x );
							 | 
						|
								            aBuffer.push_back( rectangle->GetOrigin().y );
							 | 
						|
								        }
							 | 
						|
								        else
							 | 
						|
								        {
							 | 
						|
								            for( PATHS::iterator i=paths.begin();  i!=paths.end();  ++i )
							 | 
						|
								            {
							 | 
						|
								                POINTS& plist = i->GetPoints();
							 | 
						|
								                for( unsigned jj = 0; jj < plist.size(); jj++ )
							 | 
						|
								                {
							 | 
						|
								                    aBuffer.push_back( plist[jj].x );
							 | 
						|
								                    aBuffer.push_back( plist[jj].y );
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        out->Print( nestLevel, "(%s\n", Name() );
							 | 
						|
								
							 | 
						|
								        if( rectangle )
							 | 
						|
								            rectangle->Format( out, nestLevel+1 );
							 | 
						|
								        else
							 | 
						|
								        {
							 | 
						|
								            for( PATHS::iterator i=paths.begin();  i!=paths.end();  ++i )
							 | 
						|
								                i->Format( out, nestLevel+1 );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class CIRCLE : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string layer_id;
							 | 
						|
								
							 | 
						|
								    double      diameter;
							 | 
						|
								    POINT       vertex;     // POINT's constructor sets to (0,0)
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    CIRCLE( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_circle, aParent )
							 | 
						|
								    {
							 | 
						|
								        diameter = 0.0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* newline = nestLevel ? "\n" : "";
							 | 
						|
								
							 | 
						|
								        const char* quote = out->GetQuoteChar( layer_id.c_str() );
							 | 
						|
								        out->Print( nestLevel, "(%s %s%s%s %.6g", Name(),
							 | 
						|
								                                quote, layer_id.c_str(), quote,
							 | 
						|
								                                diameter );
							 | 
						|
								
							 | 
						|
								        if( vertex.x!=0.0 || vertex.y!=0.0 )
							 | 
						|
								            out->Print( 0, " %.6g %.6g)%s", vertex.x, vertex.y, newline );
							 | 
						|
								        else
							 | 
						|
								            out->Print( 0, ")%s", newline );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetLayerId( const char* aLayerId )
							 | 
						|
								    {
							 | 
						|
								        layer_id = aLayerId;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetDiameter( double aDiameter )
							 | 
						|
								    {
							 | 
						|
								        diameter = aDiameter;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetVertex( const POINT& aVertex )
							 | 
						|
								    {
							 | 
						|
								        vertex = aVertex;
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class QARC : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string layer_id;
							 | 
						|
								    double      aperture_width;
							 | 
						|
								    POINT       vertex[3];
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    QARC( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_qarc, aParent )
							 | 
						|
								    {
							 | 
						|
								        aperture_width = 0.0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* newline = nestLevel ? "\n" : "";
							 | 
						|
								
							 | 
						|
								        const char* quote = out->GetQuoteChar( layer_id.c_str() );
							 | 
						|
								        out->Print( nestLevel, "(%s %s%s%s %.6g", Name() ,
							 | 
						|
								                                 quote, layer_id.c_str(), quote,
							 | 
						|
								                                 aperture_width);
							 | 
						|
								
							 | 
						|
								        for( int i=0;  i<3;  ++i )
							 | 
						|
								            out->Print( 0, "  %.6g %.6g",  vertex[i].x, vertex[i].y );
							 | 
						|
								
							 | 
						|
								        out->Print( 0, ")%s", newline );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetLayerId( const char* aLayerId )
							 | 
						|
								    {
							 | 
						|
								        layer_id = aLayerId;
							 | 
						|
								    }
							 | 
						|
								    void SetStart( const POINT& aStart )
							 | 
						|
								    {
							 | 
						|
								        vertex[0] = aStart;
							 | 
						|
								        // no -0.0 on the printouts!
							 | 
						|
								        vertex[0].FixNegativeZero();
							 | 
						|
								    }
							 | 
						|
								    void SetEnd( const POINT& aEnd )
							 | 
						|
								    {
							 | 
						|
								        vertex[1] = aEnd;
							 | 
						|
								        // no -0.0 on the printouts!
							 | 
						|
								        vertex[1].FixNegativeZero();
							 | 
						|
								    }
							 | 
						|
								    void SetCenter( const POINT& aCenter )
							 | 
						|
								    {
							 | 
						|
								        vertex[2] = aCenter;
							 | 
						|
								        // no -0.0 on the printouts!
							 | 
						|
								        vertex[2].FixNegativeZero();
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class WINDOW : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								protected:
							 | 
						|
								    /*  <shape_descriptor >::=
							 | 
						|
								        [<rectangle_descriptor> |
							 | 
						|
								        <circle_descriptor> |
							 | 
						|
								        <polygon_descriptor> |
							 | 
						|
								        <path_descriptor> |
							 | 
						|
								        <qarc_descriptor> ]
							 | 
						|
								    */
							 | 
						|
								    ELEM*       shape;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    WINDOW( ELEM* aParent, DSN_T aType = T_window ) :
							 | 
						|
								        ELEM( aType, aParent )
							 | 
						|
								    {
							 | 
						|
								        shape = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~WINDOW()
							 | 
						|
								    {
							 | 
						|
								        delete shape;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetShape( ELEM* aShape )
							 | 
						|
								    {
							 | 
						|
								        delete shape;
							 | 
						|
								        shape = aShape;
							 | 
						|
								
							 | 
						|
								        if( aShape )
							 | 
						|
								        {
							 | 
						|
								            wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle
							 | 
						|
								                     || aShape->Type()==T_qarc || aShape->Type()==T_path
							 | 
						|
								                     || aShape->Type()==T_polygon);
							 | 
						|
								
							 | 
						|
								            aShape->SetParent( this );
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        out->Print( nestLevel, "(%s ", Name() );
							 | 
						|
								
							 | 
						|
								        if( shape )
							 | 
						|
								            shape->Format( out, 0 );
							 | 
						|
								
							 | 
						|
								        out->Print( 0, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<WINDOW>   WINDOWS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class KEEPOUT
							 | 
						|
								 * is used for <keepout_descriptor> and <plane_descriptor>.
							 | 
						|
								 */
							 | 
						|
								class KEEPOUT : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								protected:
							 | 
						|
								    std::string     name;
							 | 
						|
								    int             sequence_number;
							 | 
						|
								    RULE*           rules;
							 | 
						|
								    RULE*           place_rules;
							 | 
						|
								
							 | 
						|
								    WINDOWS         windows;
							 | 
						|
								
							 | 
						|
								    /*  <shape_descriptor >::=
							 | 
						|
								        [<rectangle_descriptor> |
							 | 
						|
								        <circle_descriptor> |
							 | 
						|
								        <polygon_descriptor> |
							 | 
						|
								        <path_descriptor> |
							 | 
						|
								        <qarc_descriptor> ]
							 | 
						|
								    */
							 | 
						|
								    ELEM*           shape;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Constructor KEEPOUT
							 | 
						|
								     * requires a DSN_T because this class is used for T_place_keepout, T_via_keepout,
							 | 
						|
								     * T_wire_keepout, T_bend_keepout, and T_elongate_keepout as well as T_keepout.
							 | 
						|
								     */
							 | 
						|
								    KEEPOUT( ELEM* aParent, DSN_T aType ) :
							 | 
						|
								        ELEM( aType, aParent )
							 | 
						|
								    {
							 | 
						|
								        rules = 0;
							 | 
						|
								        place_rules = 0;
							 | 
						|
								        shape = 0;
							 | 
						|
								
							 | 
						|
								        sequence_number = -1;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~KEEPOUT()
							 | 
						|
								    {
							 | 
						|
								        delete rules;
							 | 
						|
								        delete place_rules;
							 | 
						|
								        delete shape;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetShape( ELEM* aShape )
							 | 
						|
								    {
							 | 
						|
								        delete shape;
							 | 
						|
								        shape = aShape;
							 | 
						|
								
							 | 
						|
								        if( aShape )
							 | 
						|
								        {
							 | 
						|
								            wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle
							 | 
						|
								                     || aShape->Type()==T_qarc || aShape->Type()==T_path
							 | 
						|
								                     || aShape->Type()==T_polygon);
							 | 
						|
								
							 | 
						|
								            aShape->SetParent( this );
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void AddWindow( WINDOW* aWindow )
							 | 
						|
								    {
							 | 
						|
								        aWindow->SetParent( this );
							 | 
						|
								        windows.push_back( aWindow );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* newline = "\n";
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, "(%s", Name() );
							 | 
						|
								
							 | 
						|
								        if( name.size() )
							 | 
						|
								        {
							 | 
						|
								            const char* quote = out->GetQuoteChar( name.c_str() );
							 | 
						|
								            out->Print( 0, " %s%s%s", quote, name.c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								        else
							 | 
						|
								            out->Print( 0, " \"\"" );   // the zone with no name or net_code == 0
							 | 
						|
								
							 | 
						|
								        if( sequence_number != -1 )
							 | 
						|
								            out->Print( 0, " (sequence_number %d)", sequence_number );
							 | 
						|
								
							 | 
						|
								        if( shape )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, " " );
							 | 
						|
								            shape->Format( out, 0 );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( rules )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "%s", newline );
							 | 
						|
								            newline = "";
							 | 
						|
								            rules->Format( out, nestLevel+1 );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( place_rules )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "%s", newline );
							 | 
						|
								            newline = "";
							 | 
						|
								            place_rules->Format( out, nestLevel+1 );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( windows.size() )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "%s", newline );
							 | 
						|
								            newline = "";
							 | 
						|
								
							 | 
						|
								            for( WINDOWS::iterator i=windows.begin();  i!=windows.end();  ++i )
							 | 
						|
								                i->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								            out->Print( nestLevel, ")\n" );
							 | 
						|
								        }
							 | 
						|
								        else
							 | 
						|
								            out->Print( 0, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<KEEPOUT>  KEEPOUTS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class VIA
							 | 
						|
								 * corresponds to the <via_descriptor> in the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								class VIA : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    STRINGS     padstacks;
							 | 
						|
								    STRINGS     spares;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    VIA( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_via, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void AppendVia( const char* aViaName )
							 | 
						|
								    {
							 | 
						|
								        padstacks.push_back( aViaName );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const int RIGHTMARGIN = 80;
							 | 
						|
								        int perLine = out->Print( nestLevel, "(%s", Name() );
							 | 
						|
								
							 | 
						|
								        for( STRINGS::iterator i=padstacks.begin();  i!=padstacks.end();  ++i )
							 | 
						|
								        {
							 | 
						|
								            if( perLine > RIGHTMARGIN )
							 | 
						|
								            {
							 | 
						|
								                out->Print( 0, "\n" );
							 | 
						|
								                perLine = out->Print( nestLevel+1, "%s", "");
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            const char* quote = out->GetQuoteChar( i->c_str() );
							 | 
						|
								            perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( spares.size() )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "\n" );
							 | 
						|
								
							 | 
						|
								            perLine = out->Print( nestLevel+1, "(spare" );
							 | 
						|
								
							 | 
						|
								            for( STRINGS::iterator i=spares.begin();  i!=spares.end();  ++i )
							 | 
						|
								            {
							 | 
						|
								                if( perLine > RIGHTMARGIN )
							 | 
						|
								                {
							 | 
						|
								                    out->Print( 0, "\n" );
							 | 
						|
								                    perLine = out->Print( nestLevel+2, "%s", "");
							 | 
						|
								                }
							 | 
						|
								                const char* quote = out->GetQuoteChar( i->c_str() );
							 | 
						|
								                perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            out->Print( 0, ")" );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        out->Print( 0, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class CLASSES : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    STRINGS         class_ids;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    CLASSES( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_classes, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        for( STRINGS::iterator i=class_ids.begin();  i!=class_ids.end();  ++i )
							 | 
						|
								        {
							 | 
						|
								            const char* quote = out->GetQuoteChar( i->c_str() );
							 | 
						|
								            out->Print( nestLevel, "%s%s%s\n", quote, i->c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class CLASS_CLASS : public ELEM_HOLDER
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    CLASSES*        classes;
							 | 
						|
								
							 | 
						|
								    /*  rule | layer_rule are put into the kids container.
							 | 
						|
								    */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Constructor CLASS_CLASS
							 | 
						|
								     * @param aParent - Parent element of the object.
							 | 
						|
								     * @param aType May be either T_class_class or T_region_class_class
							 | 
						|
								     */
							 | 
						|
								    CLASS_CLASS( ELEM* aParent, DSN_T aType ) :
							 | 
						|
								        ELEM_HOLDER( aType, aParent )
							 | 
						|
								    {
							 | 
						|
								        classes = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~CLASS_CLASS()
							 | 
						|
								    {
							 | 
						|
								        delete classes;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        if( classes )
							 | 
						|
								            classes->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        // format the kids
							 | 
						|
								        ELEM_HOLDER::FormatContents( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class CONTROL : public ELEM_HOLDER
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    bool    via_at_smd;
							 | 
						|
								    bool    via_at_smd_grid_on;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    CONTROL( ELEM* aParent ) :
							 | 
						|
								        ELEM_HOLDER( T_control, aParent )
							 | 
						|
								    {
							 | 
						|
								        via_at_smd = false;
							 | 
						|
								        via_at_smd_grid_on = false;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~CONTROL()
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        out->Print( nestLevel, "(%s\n", Name() );
							 | 
						|
								
							 | 
						|
								        //if( via_at_smd )
							 | 
						|
								        {
							 | 
						|
								            out->Print( nestLevel+1, "(via_at_smd %s", via_at_smd ? "on" : "off" );
							 | 
						|
								            if( via_at_smd_grid_on )
							 | 
						|
								                out->Print( 0, " grid %s", via_at_smd_grid_on ? "on" : "off" );
							 | 
						|
								
							 | 
						|
								            out->Print( 0, ")\n" );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        for( int i=0;  i<Length();  ++i )
							 | 
						|
								        {
							 | 
						|
								            At(i)->Format( out, nestLevel+1 );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class LAYER : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string name;
							 | 
						|
								    DSN_T       layer_type; ///< one of: T_signal, T_power, T_mixed, T_jumper
							 | 
						|
								    int         direction;
							 | 
						|
								    int         cost;       ///< [forbidden | high | medium | low | free | \<positive_integer\> | -1]
							 | 
						|
								    int         cost_type;  ///< T_length | T_way
							 | 
						|
								    RULE*       rules;
							 | 
						|
								    STRINGS     use_net;
							 | 
						|
								
							 | 
						|
								    PROPERTIES  properties;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    LAYER( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_layer, aParent )
							 | 
						|
								    {
							 | 
						|
								        layer_type = T_signal;
							 | 
						|
								        direction  = -1;
							 | 
						|
								        cost       = -1;
							 | 
						|
								        cost_type  = -1;
							 | 
						|
								
							 | 
						|
								        rules = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~LAYER()
							 | 
						|
								    {
							 | 
						|
								        delete rules;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quote = out->GetQuoteChar( name.c_str() );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, "(%s %s%s%s\n", Name(),
							 | 
						|
								                       quote, name.c_str(), quote );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel+1, "(type %s)\n", GetTokenText( layer_type ) );
							 | 
						|
								
							 | 
						|
								        if( properties.size() )
							 | 
						|
								        {
							 | 
						|
								            out->Print( nestLevel+1, "(property\n" );
							 | 
						|
								
							 | 
						|
								            for( PROPERTIES::iterator i = properties.begin();  i != properties.end();  ++i )
							 | 
						|
								            {
							 | 
						|
								                i->Format( out, nestLevel+2 );
							 | 
						|
								            }
							 | 
						|
								            out->Print( nestLevel+1, ")\n" );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( direction != -1 )
							 | 
						|
								            out->Print( nestLevel+1, "(direction %s)\n",
							 | 
						|
								                       GetTokenText( (DSN_T)direction ) );
							 | 
						|
								
							 | 
						|
								        if( rules )
							 | 
						|
								            rules->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( cost != -1 )
							 | 
						|
								        {
							 | 
						|
								            if( cost < 0 )
							 | 
						|
								                out->Print( nestLevel+1, "(cost %d", -cost );   // positive integer, stored as negative
							 | 
						|
								            else
							 | 
						|
								                out->Print( nestLevel+1, "(cost %s", GetTokenText( (DSN_T)cost ) );
							 | 
						|
								
							 | 
						|
								            if( cost_type != -1 )
							 | 
						|
								                out->Print( 0, " (type %s)", GetTokenText( (DSN_T)cost_type ) );
							 | 
						|
								
							 | 
						|
								            out->Print( 0, ")\n" );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( use_net.size() )
							 | 
						|
								        {
							 | 
						|
								            out->Print( nestLevel+1, "(use_net" );
							 | 
						|
								            for( STRINGS::const_iterator i = use_net.begin();  i!=use_net.end(); ++i )
							 | 
						|
								            {
							 | 
						|
								                quote = out->GetQuoteChar( i->c_str() );
							 | 
						|
								                out->Print( 0, " %s%s%s",  quote, i->c_str(), quote );
							 | 
						|
								            }
							 | 
						|
								            out->Print( 0, ")\n" );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								typedef boost::ptr_vector<LAYER>    LAYERS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class LAYER_PAIR : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     layer_id0;
							 | 
						|
								    std::string     layer_id1;
							 | 
						|
								
							 | 
						|
								    double          layer_weight;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    LAYER_PAIR( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_layer_pair, aParent )
							 | 
						|
								    {
							 | 
						|
								        layer_weight = 0.0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quote0 = out->GetQuoteChar( layer_id0.c_str() );
							 | 
						|
								        const char* quote1 = out->GetQuoteChar( layer_id1.c_str() );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, "(%s %s%s%s %s%s%s %.6g)\n", Name(),
							 | 
						|
								               quote0, layer_id0.c_str(), quote0,
							 | 
						|
								               quote1, layer_id1.c_str(), quote1,
							 | 
						|
								               layer_weight );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<LAYER_PAIR>  LAYER_PAIRS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class LAYER_NOISE_WEIGHT : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    LAYER_PAIRS     layer_pairs;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    LAYER_NOISE_WEIGHT( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_layer_noise_weight, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        out->Print( nestLevel, "(%s\n", Name() );
							 | 
						|
								
							 | 
						|
								        for( LAYER_PAIRS::iterator i=layer_pairs.begin(); i!=layer_pairs.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class COPPER_PLANE
							 | 
						|
								 * corresponds to a <plane_descriptor> in the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								class COPPER_PLANE : public KEEPOUT
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    COPPER_PLANE( ELEM* aParent ) :
							 | 
						|
								        KEEPOUT( aParent, T_plane )
							 | 
						|
								    {}
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<COPPER_PLANE>    COPPER_PLANES;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class TOKPROP
							 | 
						|
								 * is a container for a single property whose value is another DSN_T token.
							 | 
						|
								 * The name of the property is obtained from the DSN_T Type().
							 | 
						|
								 */
							 | 
						|
								class TOKPROP : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    DSN_T       value;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    TOKPROP( ELEM* aParent, DSN_T aType ) :
							 | 
						|
								        ELEM( aType, aParent )
							 | 
						|
								    {
							 | 
						|
								        // Do not leave uninitialized members
							 | 
						|
								        value = T_NONE;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        out->Print( nestLevel, "(%s %s)\n", Name(),
							 | 
						|
								                   GetTokenText( value ) );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class STRINGPROP
							 | 
						|
								 * is a container for a single property whose value is a string.
							 | 
						|
								 * The name of the property is obtained from the DSN_T.
							 | 
						|
								 */
							 | 
						|
								class STRINGPROP : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     value;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    STRINGPROP( ELEM* aParent, DSN_T aType ) :
							 | 
						|
								        ELEM( aType, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quote = out->GetQuoteChar( value.c_str() );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, "(%s %s%s%s)\n", Name(),
							 | 
						|
								                                quote, value.c_str(), quote );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class REGION : public ELEM_HOLDER
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     region_id;
							 | 
						|
								
							 | 
						|
								    //-----<mutually exclusive>--------------------------------------
							 | 
						|
								    RECTANGLE*      rectangle;
							 | 
						|
								    PATH*           polygon;
							 | 
						|
								    //-----</mutually exclusive>-------------------------------------
							 | 
						|
								
							 | 
						|
								    /* region_net | region_class | region_class_class are all mutually
							 | 
						|
								       exclusive and are put into the kids container.
							 | 
						|
								    */
							 | 
						|
								
							 | 
						|
								    RULE*           rules;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    REGION( ELEM* aParent ) :
							 | 
						|
								        ELEM_HOLDER( T_region, aParent )
							 | 
						|
								    {
							 | 
						|
								        rectangle = 0;
							 | 
						|
								        polygon = 0;
							 | 
						|
								        rules = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~REGION()
							 | 
						|
								    {
							 | 
						|
								        delete rectangle;
							 | 
						|
								        delete polygon;
							 | 
						|
								        delete rules;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        if( region_id.size() )
							 | 
						|
								        {
							 | 
						|
								            const char* quote = out->GetQuoteChar( region_id.c_str() );
							 | 
						|
								            out->Print( nestLevel, "%s%s%s\n", quote, region_id.c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( rectangle )
							 | 
						|
								            rectangle->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( polygon )
							 | 
						|
								            polygon->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        ELEM_HOLDER::FormatContents( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( rules )
							 | 
						|
								            rules->Format( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class GRID : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    DSN_T       grid_type;      ///< T_via | T_wire | T_via_keepout | T_place | T_snap
							 | 
						|
								    double      dimension;
							 | 
						|
								    DSN_T       direction;      ///< T_x | T_y | -1 for both
							 | 
						|
								    double      offset;
							 | 
						|
								    DSN_T       image_type;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    GRID( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_grid, aParent )
							 | 
						|
								    {
							 | 
						|
								        grid_type = T_via;
							 | 
						|
								        direction = T_NONE;
							 | 
						|
								        dimension = 0.0;
							 | 
						|
								        offset    = 0.0;
							 | 
						|
								        image_type= T_NONE;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        out->Print( nestLevel, "(%s %s %.6g",
							 | 
						|
								                   Name(),
							 | 
						|
								                   GetTokenText( grid_type ), dimension );
							 | 
						|
								
							 | 
						|
								        if( grid_type == T_place )
							 | 
						|
								        {
							 | 
						|
								            if( image_type==T_smd || image_type==T_pin )
							 | 
						|
								                out->Print( 0, " (image_type %s)", GetTokenText( image_type ) );
							 | 
						|
								        }
							 | 
						|
								        else
							 | 
						|
								        {
							 | 
						|
								            if( direction==T_x || direction==T_y )
							 | 
						|
								                out->Print( 0, " (direction %s)", GetTokenText( direction ) );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( offset != 0.0 )
							 | 
						|
								            out->Print( 0, " (offset %.6g)", offset );
							 | 
						|
								
							 | 
						|
								        out->Print( 0, ")\n");
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class STRUCTURE_OUT : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    LAYERS      layers;
							 | 
						|
								    RULE*       rules;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    STRUCTURE_OUT( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_structure_out, aParent )
							 | 
						|
								    {
							 | 
						|
								        rules = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~STRUCTURE_OUT()
							 | 
						|
								    {
							 | 
						|
								        delete rules;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        for( LAYERS::iterator i=layers.begin();  i!=layers.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( rules )
							 | 
						|
								            rules->Format( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class STRUCTURE : public ELEM_HOLDER
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    UNIT_RES*   unit;
							 | 
						|
								
							 | 
						|
								    LAYERS      layers;
							 | 
						|
								
							 | 
						|
								    LAYER_NOISE_WEIGHT*  layer_noise_weight;
							 | 
						|
								
							 | 
						|
								    BOUNDARY*   boundary;
							 | 
						|
								    BOUNDARY*   place_boundary;
							 | 
						|
								    VIA*        via;
							 | 
						|
								    CONTROL*    control;
							 | 
						|
								    RULE*       rules;
							 | 
						|
								
							 | 
						|
								    KEEPOUTS    keepouts;
							 | 
						|
								
							 | 
						|
								    COPPER_PLANES      planes;
							 | 
						|
								
							 | 
						|
								    typedef boost::ptr_vector<REGION>   REGIONS;
							 | 
						|
								    REGIONS     regions;
							 | 
						|
								
							 | 
						|
								    RULE*       place_rules;
							 | 
						|
								
							 | 
						|
								    typedef boost::ptr_vector<GRID>     GRIDS;
							 | 
						|
								    GRIDS       grids;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    STRUCTURE( ELEM* aParent ) :
							 | 
						|
								        ELEM_HOLDER( T_structure, aParent )
							 | 
						|
								    {
							 | 
						|
								        unit = 0;
							 | 
						|
								        layer_noise_weight = 0;
							 | 
						|
								        boundary = 0;
							 | 
						|
								        place_boundary = 0;
							 | 
						|
								        via = 0;
							 | 
						|
								        control = 0;
							 | 
						|
								        rules = 0;
							 | 
						|
								        place_rules = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~STRUCTURE()
							 | 
						|
								    {
							 | 
						|
								        delete unit;
							 | 
						|
								        delete layer_noise_weight;
							 | 
						|
								        delete boundary;
							 | 
						|
								        delete place_boundary;
							 | 
						|
								        delete via;
							 | 
						|
								        delete control;
							 | 
						|
								        delete rules;
							 | 
						|
								        delete place_rules;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetBOUNDARY( BOUNDARY *aBoundary )
							 | 
						|
								    {
							 | 
						|
								        delete boundary;
							 | 
						|
								        boundary = aBoundary;
							 | 
						|
								        if( boundary )
							 | 
						|
								        {
							 | 
						|
								            boundary->SetParent( this );
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetPlaceBOUNDARY( BOUNDARY *aBoundary )
							 | 
						|
								    {
							 | 
						|
								        delete place_boundary;
							 | 
						|
								        place_boundary = aBoundary;
							 | 
						|
								        if( place_boundary )
							 | 
						|
								            place_boundary->SetParent( this );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        if( unit )
							 | 
						|
								            unit->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( LAYERS::iterator i=layers.begin();  i!=layers.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( layer_noise_weight )
							 | 
						|
								            layer_noise_weight->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( boundary )
							 | 
						|
								            boundary->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( place_boundary )
							 | 
						|
								            place_boundary->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( COPPER_PLANES::iterator i=planes.begin();  i!=planes.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( REGIONS::iterator i=regions.begin();  i!=regions.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( KEEPOUTS::iterator i=keepouts.begin();  i!=keepouts.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( via )
							 | 
						|
								            via->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( control )
							 | 
						|
								            control->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( int i=0; i<Length();  ++i )
							 | 
						|
								        {
							 | 
						|
								            At(i)->Format( out, nestLevel );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( rules )
							 | 
						|
								            rules->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( place_rules )
							 | 
						|
								            place_rules->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( GRIDS::iterator i=grids.begin();  i!=grids.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    UNIT_RES* GetUnits() const
							 | 
						|
								    {
							 | 
						|
								        if( unit )
							 | 
						|
								            return unit;
							 | 
						|
								
							 | 
						|
								        return ELEM::GetUnits();
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class PLACE
							 | 
						|
								 * implements the <placement_reference> in the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								class PLACE : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     component_id;       ///< reference designator
							 | 
						|
								
							 | 
						|
								    DSN_T           side;
							 | 
						|
								
							 | 
						|
								    double          rotation;
							 | 
						|
								
							 | 
						|
								    bool            hasVertex;
							 | 
						|
								    POINT           vertex;
							 | 
						|
								
							 | 
						|
								    DSN_T           mirror;
							 | 
						|
								    DSN_T           status;
							 | 
						|
								
							 | 
						|
								    std::string     logical_part;
							 | 
						|
								
							 | 
						|
								    RULE*           place_rules;
							 | 
						|
								
							 | 
						|
								    PROPERTIES      properties;
							 | 
						|
								
							 | 
						|
								    DSN_T           lock_type;
							 | 
						|
								
							 | 
						|
								    //-----<mutually exclusive>--------------
							 | 
						|
								    RULE*           rules;
							 | 
						|
								    REGION*         region;
							 | 
						|
								    //-----</mutually exclusive>-------------
							 | 
						|
								
							 | 
						|
								    std::string     part_number;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    PLACE( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_place, aParent )
							 | 
						|
								    {
							 | 
						|
								        side = T_front;
							 | 
						|
								
							 | 
						|
								        rotation = 0.0;
							 | 
						|
								
							 | 
						|
								        hasVertex = false;
							 | 
						|
								
							 | 
						|
								        mirror = T_NONE;
							 | 
						|
								        status = T_NONE;
							 | 
						|
								
							 | 
						|
								        place_rules = 0;
							 | 
						|
								
							 | 
						|
								        lock_type = T_NONE;
							 | 
						|
								        rules = 0;
							 | 
						|
								        region = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~PLACE()
							 | 
						|
								    {
							 | 
						|
								        delete place_rules;
							 | 
						|
								        delete rules;
							 | 
						|
								        delete region;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetVertex( const POINT& aVertex )
							 | 
						|
								    {
							 | 
						|
								        vertex = aVertex;
							 | 
						|
								        vertex.FixNegativeZero();
							 | 
						|
								        hasVertex = true;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetRotation( double aRotation )
							 | 
						|
								    {
							 | 
						|
								        rotation = aRotation;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR );
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<PLACE>    PLACES;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class COMPONENT
							 | 
						|
								 * implements the <component_descriptor> in the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								class COMPONENT : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								//    std::string     hash;       ///< a hash string used by Compare(), not Format()ed/exported.
							 | 
						|
								
							 | 
						|
								    std::string     image_id;
							 | 
						|
								    PLACES          places;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    COMPONENT( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_component, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    const std::string& GetImageId() const  { return image_id; }
							 | 
						|
								    void SetImageId( const std::string& aImageId )
							 | 
						|
								    {
							 | 
						|
								        image_id = aImageId;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function Compare
							 | 
						|
								     * compares two objects of this type and returns <0, 0, or >0.
							 | 
						|
								     */
							 | 
						|
								//    static int Compare( IMAGE* lhs, IMAGE* rhs );
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quote = out->GetQuoteChar( image_id.c_str() );
							 | 
						|
								        out->Print( nestLevel, "(%s %s%s%s\n", Name(),
							 | 
						|
								                                quote, image_id.c_str(), quote );
							 | 
						|
								
							 | 
						|
								        FormatContents( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        for( PLACES::iterator i=places.begin();  i!=places.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<COMPONENT> COMPONENTS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class PLACEMENT : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    UNIT_RES*   unit;
							 | 
						|
								
							 | 
						|
								    DSN_T       flip_style;
							 | 
						|
								
							 | 
						|
								    COMPONENTS  components;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    PLACEMENT( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_placement, aParent )
							 | 
						|
								    {
							 | 
						|
								        unit = 0;
							 | 
						|
								        flip_style = DSN_T( T_NONE );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~PLACEMENT()
							 | 
						|
								    {
							 | 
						|
								        delete unit;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function LookupCOMPONENT
							 | 
						|
								     * looks up a COMPONENT by name.  If the name is not found, a new
							 | 
						|
								     * COMPONENT is added to the components container.  At any time the
							 | 
						|
								     * names in the component container should remain unique.
							 | 
						|
								     * @return COMPONENT* - an existing or new
							 | 
						|
								     */
							 | 
						|
								    COMPONENT* LookupCOMPONENT( const std::string& imageName )
							 | 
						|
								    {
							 | 
						|
								        for( unsigned i=0; i<components.size();  ++i )
							 | 
						|
								        {
							 | 
						|
								            if( 0 == components[i].GetImageId().compare( imageName ) )
							 | 
						|
								                return &components[i];
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        COMPONENT* added = new COMPONENT(this);
							 | 
						|
								        components.push_back( added );
							 | 
						|
								        added->SetImageId( imageName );
							 | 
						|
								        return added;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        if( unit )
							 | 
						|
								            unit->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( flip_style != DSN_T( T_NONE ) )
							 | 
						|
								        {
							 | 
						|
								            out->Print( nestLevel, "(place_control (flip_style %s))\n",
							 | 
						|
								                       GetTokenText( flip_style ) );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        for( COMPONENTS::iterator i=components.begin();  i!=components.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    UNIT_RES* GetUnits() const
							 | 
						|
								    {
							 | 
						|
								        if( unit )
							 | 
						|
								            return unit;
							 | 
						|
								
							 | 
						|
								        return ELEM::GetUnits();
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class SHAPE
							 | 
						|
								 * corresponds to the "(shape ..)" element in the specctra dsn spec.
							 | 
						|
								 * It is not a <shape_descriptor>, which is one of things that this
							 | 
						|
								 * elements contains, i.e. in its "shape" field.  This class also implements
							 | 
						|
								 * the "(outline ...)" element as a dual personality.
							 | 
						|
								 */
							 | 
						|
								class SHAPE : public WINDOW
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    DSN_T           connect;
							 | 
						|
								
							 | 
						|
								    /*  <shape_descriptor >::=
							 | 
						|
								        [<rectangle_descriptor> |
							 | 
						|
								        <circle_descriptor> |
							 | 
						|
								        <polygon_descriptor> |
							 | 
						|
								        <path_descriptor> |
							 | 
						|
								        <qarc_descriptor> ]
							 | 
						|
								    ELEM*           shape;      // inherited from WINDOW
							 | 
						|
								    */
							 | 
						|
								
							 | 
						|
								    WINDOWS         windows;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Constructor SHAPE
							 | 
						|
								     * alternatively takes a DSN_T aType of T_outline
							 | 
						|
								     */
							 | 
						|
								    SHAPE( ELEM* aParent, DSN_T aType = T_shape ) :
							 | 
						|
								        WINDOW( aParent, aType )
							 | 
						|
								    {
							 | 
						|
								        connect = T_on;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetConnect( DSN_T aConnect )
							 | 
						|
								    {
							 | 
						|
								        connect = aConnect;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        out->Print( nestLevel, "(%s ", Name() );
							 | 
						|
								
							 | 
						|
								        if( shape )
							 | 
						|
								            shape->Format( out, 0 );
							 | 
						|
								
							 | 
						|
								        if( connect == T_off )
							 | 
						|
								            out->Print( 0, "(connect %s)", GetTokenText( connect ) );
							 | 
						|
								
							 | 
						|
								        if( windows.size() )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "\n" );
							 | 
						|
								
							 | 
						|
								            for( WINDOWS::iterator i=windows.begin();  i!=windows.end();  ++i )
							 | 
						|
								                i->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								            out->Print( nestLevel, ")\n" );
							 | 
						|
								        }
							 | 
						|
								        else
							 | 
						|
								            out->Print( 0, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class PIN : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     padstack_id;
							 | 
						|
								    double          rotation;
							 | 
						|
								    bool            isRotated;
							 | 
						|
								    std::string     pin_id;
							 | 
						|
								    POINT           vertex;
							 | 
						|
								
							 | 
						|
								    int             kiNetCode;      ///< KiCad netcode
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    PIN( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_pin, aParent )
							 | 
						|
								    {
							 | 
						|
								        rotation = 0.0;
							 | 
						|
								        isRotated = false;
							 | 
						|
								        kiNetCode = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetRotation( double aRotation )
							 | 
						|
								    {
							 | 
						|
								        rotation = aRotation;
							 | 
						|
								        isRotated = (aRotation != 0.0);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetVertex( const POINT& aPoint )
							 | 
						|
								    {
							 | 
						|
								        vertex = aPoint;
							 | 
						|
								        vertex.FixNegativeZero();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quote = out->GetQuoteChar( padstack_id.c_str() );
							 | 
						|
								        if( isRotated )
							 | 
						|
								            out->Print( nestLevel, "(pin %s%s%s (rotate %.6g)",
							 | 
						|
								                                     quote, padstack_id.c_str(), quote,
							 | 
						|
								                                     rotation
							 | 
						|
								                                     );
							 | 
						|
								        else
							 | 
						|
								            out->Print( nestLevel, "(pin %s%s%s", quote, padstack_id.c_str(), quote );
							 | 
						|
								
							 | 
						|
								        quote = out->GetQuoteChar( pin_id.c_str() );
							 | 
						|
								        out->Print( 0, " %s%s%s %.6g %.6g)\n", quote, pin_id.c_str(), quote,
							 | 
						|
								                   vertex.x, vertex.y );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<PIN>  PINS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class LIBRARY;
							 | 
						|
								class IMAGE : public ELEM_HOLDER
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								    friend class LIBRARY;
							 | 
						|
								
							 | 
						|
								    std::string     hash;       ///< a hash string used by Compare(), not Format()ed/exported.
							 | 
						|
								
							 | 
						|
								    std::string     image_id;
							 | 
						|
								    DSN_T           side;
							 | 
						|
								    UNIT_RES*       unit;
							 | 
						|
								
							 | 
						|
								    /*  The grammar spec says only one outline is supported, but I am seeing
							 | 
						|
								        *.dsn examples with multiple outlines.  So the outlines will go into
							 | 
						|
								        the kids list.
							 | 
						|
								    */
							 | 
						|
								
							 | 
						|
								    PINS            pins;
							 | 
						|
								
							 | 
						|
								    RULE*           rules;
							 | 
						|
								    RULE*           place_rules;
							 | 
						|
								
							 | 
						|
								    KEEPOUTS        keepouts;
							 | 
						|
								
							 | 
						|
								    int             duplicated;     ///< no. times this image_id is duplicated
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    IMAGE( ELEM* aParent ) :
							 | 
						|
								        ELEM_HOLDER( T_image, aParent )
							 | 
						|
								    {
							 | 
						|
								        side = T_both;
							 | 
						|
								        unit = 0;
							 | 
						|
								        rules = 0;
							 | 
						|
								        place_rules = 0;
							 | 
						|
								        duplicated = 0;
							 | 
						|
								    }
							 | 
						|
								    ~IMAGE()
							 | 
						|
								    {
							 | 
						|
								        delete unit;
							 | 
						|
								        delete rules;
							 | 
						|
								        delete place_rules;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function Compare
							 | 
						|
								     * compares two objects of this type and returns <0, 0, or >0.
							 | 
						|
								     */
							 | 
						|
								    static int Compare( IMAGE* lhs, IMAGE* rhs );
							 | 
						|
								
							 | 
						|
								    std::string GetImageId()
							 | 
						|
								    {
							 | 
						|
								        if( duplicated )
							 | 
						|
								        {
							 | 
						|
								            char    buf[32];
							 | 
						|
								
							 | 
						|
								            std::string ret = image_id;
							 | 
						|
								            ret += "::";
							 | 
						|
								            sprintf( buf, "%d", duplicated );
							 | 
						|
								            ret += buf;
							 | 
						|
								            return ret;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        return image_id;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        std::string imageId = GetImageId();
							 | 
						|
								
							 | 
						|
								        const char* quote = out->GetQuoteChar( imageId.c_str() );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, "(%s %s%s%s", Name(),
							 | 
						|
								                                quote, imageId.c_str(), quote );
							 | 
						|
								
							 | 
						|
								        FormatContents( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // this is here for makeHash()
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        if( side != T_both )
							 | 
						|
								            out->Print( 0, " (side %s)", GetTokenText( side ) );
							 | 
						|
								
							 | 
						|
								        out->Print( 0, "\n");
							 | 
						|
								
							 | 
						|
								        if( unit )
							 | 
						|
								            unit->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        // format the kids, which in this class are the shapes
							 | 
						|
								        ELEM_HOLDER::FormatContents( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( PINS::iterator i=pins.begin();  i!=pins.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( rules )
							 | 
						|
								            rules->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( place_rules )
							 | 
						|
								            place_rules->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( KEEPOUTS::iterator i=keepouts.begin();  i!=keepouts.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    UNIT_RES* GetUnits() const
							 | 
						|
								    {
							 | 
						|
								        if( unit )
							 | 
						|
								            return unit;
							 | 
						|
								
							 | 
						|
								        return ELEM::GetUnits();
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<IMAGE>    IMAGES;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class PADSTACK
							 | 
						|
								 * holds either a via or a pad definition.
							 | 
						|
								 */
							 | 
						|
								class PADSTACK : public ELEM_HOLDER
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     hash;       ///< a hash string used by Compare(), not Format()ed/exported.
							 | 
						|
								
							 | 
						|
								    std::string     padstack_id;
							 | 
						|
								    UNIT_RES*       unit;
							 | 
						|
								
							 | 
						|
								    /* The shapes are stored in the kids list */
							 | 
						|
								
							 | 
						|
								    DSN_T           rotate;
							 | 
						|
								    DSN_T           absolute;
							 | 
						|
								    DSN_T           attach;
							 | 
						|
								    std::string     via_id;
							 | 
						|
								
							 | 
						|
								    RULE*           rules;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Constructor PADSTACK()
							 | 
						|
								     * cannot take ELEM* aParent because PADSTACKSET confuses this with a
							 | 
						|
								     * copy constructor and causes havoc.  Instead set parent with
							 | 
						|
								     * LIBRARY::AddPadstack()
							 | 
						|
								     */
							 | 
						|
								    PADSTACK() :
							 | 
						|
								        ELEM_HOLDER( T_padstack, NULL )
							 | 
						|
								    {
							 | 
						|
								        unit = 0;
							 | 
						|
								        rotate = T_on;
							 | 
						|
								        absolute = T_off;
							 | 
						|
								        rules = 0;
							 | 
						|
								        attach = T_off;
							 | 
						|
								    }
							 | 
						|
								    ~PADSTACK()
							 | 
						|
								    {
							 | 
						|
								        delete unit;
							 | 
						|
								        delete rules;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    const std::string& GetPadstackId()
							 | 
						|
								    {
							 | 
						|
								        return padstack_id;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function Compare
							 | 
						|
								     * compares two objects of this type and returns <0, 0, or >0.
							 | 
						|
								     */
							 | 
						|
								    static int Compare( PADSTACK* lhs, PADSTACK* rhs );
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    void SetPadstackId( const char* aPadstackId )
							 | 
						|
								    {
							 | 
						|
								        padstack_id = aPadstackId;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quote = out->GetQuoteChar( padstack_id.c_str() );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, "(%s %s%s%s\n", Name(),
							 | 
						|
								                                quote, padstack_id.c_str(), quote );
							 | 
						|
								
							 | 
						|
								        FormatContents( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    // this factored out for use by Compare()
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        if( unit )
							 | 
						|
								            unit->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        // format the kids, which in this class are the shapes
							 | 
						|
								        ELEM_HOLDER::FormatContents( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, "%s", "" );
							 | 
						|
								
							 | 
						|
								        // spec for <attach_descriptor> says default is on, so
							 | 
						|
								        // print the off condition to override this.
							 | 
						|
								        if( attach == T_off )
							 | 
						|
								            out->Print( 0, "(attach off)" );
							 | 
						|
								        else if( attach == T_on )
							 | 
						|
								        {
							 | 
						|
								            const char* quote = out->GetQuoteChar( via_id.c_str() );
							 | 
						|
								            out->Print( 0, "(attach on (use_via %s%s%s))",
							 | 
						|
								                       quote, via_id.c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( rotate == T_off )   // print the non-default
							 | 
						|
								            out->Print( 0, "(rotate %s)", GetTokenText( rotate ) );
							 | 
						|
								
							 | 
						|
								        if( absolute == T_on )  // print the non-default
							 | 
						|
								            out->Print( 0, "(absolute %s)", GetTokenText( absolute ) );
							 | 
						|
								
							 | 
						|
								        out->Print( 0, "\n" );
							 | 
						|
								
							 | 
						|
								        if( rules )
							 | 
						|
								            rules->Format( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    UNIT_RES* GetUnits() const
							 | 
						|
								    {
							 | 
						|
								        if( unit )
							 | 
						|
								            return unit;
							 | 
						|
								
							 | 
						|
								        return ELEM::GetUnits();
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<PADSTACK> PADSTACKS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Function operator<
							 | 
						|
								 * is used by the PADSTACKSET boost::ptr_set below
							 | 
						|
								 */
							 | 
						|
								inline bool operator<( const PADSTACK& lhs, const PADSTACK& rhs )
							 | 
						|
								{
							 | 
						|
								    return PADSTACK::Compare( (PADSTACK*) &lhs, (PADSTACK*) &rhs ) < 0;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class LIBRARY
							 | 
						|
								 * corresponds to the <library_descriptor> in the specctra dsn specification.
							 | 
						|
								 * Only unit_descriptor, image_descriptors, and padstack_descriptors are
							 | 
						|
								 * included as children at this time.
							 | 
						|
								 */
							 | 
						|
								class LIBRARY : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    UNIT_RES*       unit;
							 | 
						|
								    IMAGES          images;
							 | 
						|
								
							 | 
						|
								    PADSTACKS       padstacks;      ///< all except vias, which are in 'vias'
							 | 
						|
								    PADSTACKS       vias;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    LIBRARY( ELEM* aParent, DSN_T aType = T_library ) :
							 | 
						|
								        ELEM( aType, aParent )
							 | 
						|
								    {
							 | 
						|
								        unit = 0;
							 | 
						|
								//        via_start_index = -1;       // 0 or greater means there is at least one via
							 | 
						|
								    }
							 | 
						|
								    ~LIBRARY()
							 | 
						|
								    {
							 | 
						|
								        delete unit;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void AddPadstack( PADSTACK* aPadstack )
							 | 
						|
								    {
							 | 
						|
								        aPadstack->SetParent( this );
							 | 
						|
								        padstacks.push_back( aPadstack );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								/*
							 | 
						|
								    void SetViaStartIndex( int aIndex )
							 | 
						|
								    {
							 | 
						|
								        via_start_index = aIndex;
							 | 
						|
								    }
							 | 
						|
								    int GetViaStartIndex()
							 | 
						|
								    {
							 | 
						|
								        return via_start_index;
							 | 
						|
								    }
							 | 
						|
								*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function FindIMAGE
							 | 
						|
								     * searches this LIBRARY for an image which matches the argument.
							 | 
						|
								     * @return int - if found the index into the images list, else -1.
							 | 
						|
								     */
							 | 
						|
								    int FindIMAGE( IMAGE* aImage )
							 | 
						|
								    {
							 | 
						|
								        unsigned i;
							 | 
						|
								        for( i=0;  i<images.size();  ++i )
							 | 
						|
								        {
							 | 
						|
								            if( 0 == IMAGE::Compare( aImage, &images[i] ) )
							 | 
						|
								                return (int) i;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // There is no match to the IMAGE contents, but now generate a unique
							 | 
						|
								        // name for it.
							 | 
						|
								        int dups = 1;
							 | 
						|
								        for( i=0;  i<images.size();  ++i )
							 | 
						|
								        {
							 | 
						|
								            if( 0 == aImage->image_id.compare( images[i].image_id ) )
							 | 
						|
								                aImage->duplicated = dups++;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        return -1;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function AppendIMAGE
							 | 
						|
								     * adds the image to the image list.
							 | 
						|
								     */
							 | 
						|
								    void AppendIMAGE( IMAGE* aImage )
							 | 
						|
								    {
							 | 
						|
								        aImage->SetParent( this );
							 | 
						|
								        images.push_back( aImage );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function LookupIMAGE
							 | 
						|
								     * will add the image only if one exactly like it does not already exist
							 | 
						|
								     * in the image container.
							 | 
						|
								     * @return IMAGE* - the IMAGE which is registered in the LIBRARY that
							 | 
						|
								     *           matches the argument, and it will be either the argument or
							 | 
						|
								     *           a previous image which is a duplicate.
							 | 
						|
								     */
							 | 
						|
								    IMAGE* LookupIMAGE( IMAGE* aImage )
							 | 
						|
								    {
							 | 
						|
								        int ndx = FindIMAGE( aImage );
							 | 
						|
								        if( ndx == -1 )
							 | 
						|
								        {
							 | 
						|
								            AppendIMAGE( aImage );
							 | 
						|
								            return aImage;
							 | 
						|
								        }
							 | 
						|
								        return &images[ndx];
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function FindVia
							 | 
						|
								     * searches this LIBRARY for a via which matches the argument.
							 | 
						|
								     * @return int - if found the index into the padstack list, else -1.
							 | 
						|
								     */
							 | 
						|
								    int FindVia( PADSTACK* aVia )
							 | 
						|
								    {
							 | 
						|
								        for( unsigned i=0;  i<vias.size();  ++i )
							 | 
						|
								        {
							 | 
						|
								            if( 0 == PADSTACK::Compare( aVia, &vias[i] ) )
							 | 
						|
								                return int( i );
							 | 
						|
								        }
							 | 
						|
								        return -1;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function AppendVia
							 | 
						|
								     * adds \a aVia to the internal via container.
							 | 
						|
								     */
							 | 
						|
								    void AppendVia( PADSTACK* aVia )
							 | 
						|
								    {
							 | 
						|
								        aVia->SetParent( this );
							 | 
						|
								        vias.push_back( aVia );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function AppendPADSTACK
							 | 
						|
								     * adds the padstack to the padstack container.
							 | 
						|
								     */
							 | 
						|
								    void AppendPADSTACK( PADSTACK* aPadstack )
							 | 
						|
								    {
							 | 
						|
								        aPadstack->SetParent( this );
							 | 
						|
								        padstacks.push_back( aPadstack );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function LookupVia
							 | 
						|
								     * will add the via only if one exactly like it does not already exist
							 | 
						|
								     * in the padstack container.
							 | 
						|
								     * @return PADSTACK* - the PADSTACK which is registered in the LIBRARY that
							 | 
						|
								     *           matches the argument, and it will be either the argument or
							 | 
						|
								     *           a previous padstack which is a duplicate.
							 | 
						|
								     */
							 | 
						|
								    PADSTACK* LookupVia( PADSTACK* aVia )
							 | 
						|
								    {
							 | 
						|
								        int ndx = FindVia( aVia );
							 | 
						|
								        if( ndx == -1 )
							 | 
						|
								        {
							 | 
						|
								            AppendVia( aVia );
							 | 
						|
								            return aVia;
							 | 
						|
								        }
							 | 
						|
								        return &vias[ndx];
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function FindPADSTACK
							 | 
						|
								     * searches the padstack container by name.
							 | 
						|
								     * @return PADSTACK* - The PADSTACK with a matching name if it exists, else NULL.
							 | 
						|
								     */
							 | 
						|
								    PADSTACK* FindPADSTACK( const std::string& aPadstackId )
							 | 
						|
								    {
							 | 
						|
								        for( unsigned i=0;  i<padstacks.size();  ++i )
							 | 
						|
								        {
							 | 
						|
								            PADSTACK* ps = &padstacks[i];
							 | 
						|
								            if( 0 == ps->GetPadstackId().compare( aPadstackId ) )
							 | 
						|
								                return ps;
							 | 
						|
								        }
							 | 
						|
								        return NULL;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        if( unit )
							 | 
						|
								            unit->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( IMAGES::iterator i=images.begin();  i!=images.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( PADSTACKS::iterator i=padstacks.begin();  i!=padstacks.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( PADSTACKS::iterator i=vias.begin();  i!=vias.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    UNIT_RES* GetUnits() const
							 | 
						|
								    {
							 | 
						|
								        if( unit )
							 | 
						|
								            return unit;
							 | 
						|
								
							 | 
						|
								        return ELEM::GetUnits();
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class PIN_REF
							 | 
						|
								 * corresponds to the <pin_reference> definition in the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								struct PIN_REF : public ELEM
							 | 
						|
								{
							 | 
						|
								    std::string     component_id;
							 | 
						|
								    std::string     pin_id;
							 | 
						|
								
							 | 
						|
								    PIN_REF( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_pin, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function FormatIt
							 | 
						|
								     * is like Format() but is not virual and returns the number of characters
							 | 
						|
								     * that were output.
							 | 
						|
								     */
							 | 
						|
								    int FormatIt( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        // only print the newline if there is a nest level, and make
							 | 
						|
								        // the quotes unconditional on this one.
							 | 
						|
								        const char* newline = nestLevel ? "\n" : "";
							 | 
						|
								
							 | 
						|
								        const char* cquote = out->GetQuoteChar( component_id.c_str() );
							 | 
						|
								        const char* pquote = out->GetQuoteChar( pin_id.c_str() );
							 | 
						|
								
							 | 
						|
								        return out->Print( nestLevel, "%s%s%s-%s%s%s%s",
							 | 
						|
								                cquote, component_id.c_str(), cquote,
							 | 
						|
								                pquote, pin_id.c_str(), pquote,
							 | 
						|
								                newline );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef std::vector<PIN_REF>   PIN_REFS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class FROMTO : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     fromText;
							 | 
						|
								    std::string     toText;
							 | 
						|
								
							 | 
						|
								    DSN_T           fromto_type;
							 | 
						|
								    std::string     net_id;
							 | 
						|
								    RULE*           rules;
							 | 
						|
								//    std::string     circuit;
							 | 
						|
								    LAYER_RULES     layer_rules;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    FROMTO( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_fromto, aParent )
							 | 
						|
								    {
							 | 
						|
								        rules = 0;
							 | 
						|
								        fromto_type  = DSN_T( T_NONE );
							 | 
						|
								    }
							 | 
						|
								    ~FROMTO()
							 | 
						|
								    {
							 | 
						|
								        delete rules;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        // no quoting on these two, the lexer preserved the quotes on input
							 | 
						|
								        out->Print( nestLevel, "(%s %s %s ",
							 | 
						|
								                 Name(), fromText.c_str(), toText.c_str() );
							 | 
						|
								
							 | 
						|
								        if( fromto_type != DSN_T( T_NONE ) )
							 | 
						|
								            out->Print( 0, "(type %s)", GetTokenText( fromto_type ) );
							 | 
						|
								
							 | 
						|
								        if( net_id.size() )
							 | 
						|
								        {
							 | 
						|
								            const char* quote = out->GetQuoteChar( net_id.c_str() );
							 | 
						|
								            out->Print( 0, "(net %s%s%s)",  quote, net_id.c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        bool singleLine = true;
							 | 
						|
								
							 | 
						|
								        if( rules || layer_rules.size() )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "\n" );
							 | 
						|
								            singleLine = false;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( rules )
							 | 
						|
								            rules->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        /*
							 | 
						|
								        if( circuit.size() )
							 | 
						|
								            out->Print( nestLevel, "%s\n", circuit.c_str() );
							 | 
						|
								        */
							 | 
						|
								
							 | 
						|
								        for( LAYER_RULES::iterator i=layer_rules.begin();  i!=layer_rules.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        out->Print( singleLine ? 0 : nestLevel, ")" );
							 | 
						|
								        if( nestLevel || !singleLine )
							 | 
						|
								            out->Print( 0, "\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<FROMTO>       FROMTOS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class COMP_ORDER
							 | 
						|
								 * corresponds to the <component_order_descriptor>
							 | 
						|
								 */
							 | 
						|
								class COMP_ORDER : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    STRINGS         placement_ids;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    COMP_ORDER( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_comp_order, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        out->Print( nestLevel, "(%s", Name() );
							 | 
						|
								
							 | 
						|
								        for( STRINGS::iterator i=placement_ids.begin();  i!=placement_ids.end();  ++i )
							 | 
						|
								        {
							 | 
						|
								            const char* quote = out->GetQuoteChar( i->c_str() );
							 | 
						|
								            out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        out->Print( 0, ")" );
							 | 
						|
								        if( nestLevel )
							 | 
						|
								            out->Print( 0, "\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<COMP_ORDER>   COMP_ORDERS;
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class NET
							 | 
						|
								 * corresponds to a <net_descriptor>
							 | 
						|
								 * in the DSN spec.
							 | 
						|
								 */
							 | 
						|
								class NET : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     net_id;
							 | 
						|
								    bool            unassigned;
							 | 
						|
								    int             net_number;
							 | 
						|
								
							 | 
						|
								    DSN_T           pins_type;      ///< T_pins | T_order, type of field 'pins' below
							 | 
						|
								    PIN_REFS        pins;
							 | 
						|
								
							 | 
						|
								    PIN_REFS        expose;
							 | 
						|
								    PIN_REFS        noexpose;
							 | 
						|
								    PIN_REFS        source;
							 | 
						|
								    PIN_REFS        load;
							 | 
						|
								    PIN_REFS        terminator;
							 | 
						|
								
							 | 
						|
								    DSN_T           type;           ///< T_fix | T_normal
							 | 
						|
								
							 | 
						|
								    DSN_T           supply;         ///< T_power | T_ground
							 | 
						|
								
							 | 
						|
								    RULE*           rules;
							 | 
						|
								
							 | 
						|
								    LAYER_RULES     layer_rules;
							 | 
						|
								
							 | 
						|
								    FROMTOS         fromtos;
							 | 
						|
								
							 | 
						|
								    COMP_ORDER*     comp_order;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    NET( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_net, aParent )
							 | 
						|
								    {
							 | 
						|
								        unassigned = false;
							 | 
						|
								        net_number = T_NONE;
							 | 
						|
								        pins_type = T_pins;
							 | 
						|
								
							 | 
						|
								        type = T_NONE;
							 | 
						|
								        supply = T_NONE;
							 | 
						|
								
							 | 
						|
								        rules = 0;
							 | 
						|
								        comp_order = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~NET()
							 | 
						|
								    {
							 | 
						|
								        delete rules;
							 | 
						|
								        delete comp_order;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    int FindPIN_REF( const std::string& aComponent )
							 | 
						|
								    {
							 | 
						|
								        for( unsigned i=0;  i<pins.size();  ++i )
							 | 
						|
								        {
							 | 
						|
								            if( 0 == aComponent.compare( pins[i].component_id ) )
							 | 
						|
								                return int(i);
							 | 
						|
								        }
							 | 
						|
								        return -1;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quote = out->GetQuoteChar( net_id.c_str() );
							 | 
						|
								        const char* space = " ";
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, "(%s %s%s%s", Name(),
							 | 
						|
								                   quote, net_id.c_str(), quote );
							 | 
						|
								
							 | 
						|
								        if( unassigned )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "%s(unassigned)", space );
							 | 
						|
								            space = "";         // only needed one space
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( net_number != T_NONE )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "%s(net_number %d)", space, net_number );
							 | 
						|
								            // space = "";
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        out->Print( 0, "\n" );
							 | 
						|
								
							 | 
						|
								        if( pins.size() )
							 | 
						|
								        {
							 | 
						|
								            const int RIGHTMARGIN = 80;
							 | 
						|
								            int perLine = out->Print( nestLevel+1, "(%s", GetTokenText( pins_type ) );
							 | 
						|
								
							 | 
						|
								            for( PIN_REFS::iterator i=pins.begin();  i!=pins.end();  ++i )
							 | 
						|
								            {
							 | 
						|
								                if( perLine > RIGHTMARGIN )
							 | 
						|
								                {
							 | 
						|
								                    out->Print( 0, "\n");
							 | 
						|
								                    perLine = out->Print( nestLevel+2, "%s", "" );
							 | 
						|
								                }
							 | 
						|
								                else
							 | 
						|
								                    perLine += out->Print( 0, " " );
							 | 
						|
								
							 | 
						|
								                perLine += i->FormatIt( out, 0 );
							 | 
						|
								            }
							 | 
						|
								            out->Print( 0, ")\n" );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( comp_order )
							 | 
						|
								            comp_order->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( type != T_NONE )
							 | 
						|
								            out->Print( nestLevel+1, "(type %s)\n", GetTokenText( type ) );
							 | 
						|
								
							 | 
						|
								        if( rules )
							 | 
						|
								            rules->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        for( LAYER_RULES::iterator i=layer_rules.begin();  i!=layer_rules.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        for( FROMTOS::iterator i=fromtos.begin();  i!=fromtos.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<NET>  NETS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class TOPOLOGY : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    FROMTOS         fromtos;
							 | 
						|
								
							 | 
						|
								    COMP_ORDERS     comp_orders;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    TOPOLOGY( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_topology, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        for( FROMTOS::iterator i=fromtos.begin();  i!=fromtos.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( COMP_ORDERS::iterator i=comp_orders.begin();  i!=comp_orders.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class CLASS
							 | 
						|
								 * corresponds to the <class_descriptor> in the specctra spec.
							 | 
						|
								 */
							 | 
						|
								class CLASS : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     class_id;
							 | 
						|
								
							 | 
						|
								    STRINGS         net_ids;
							 | 
						|
								
							 | 
						|
								    /// circuit descriptor list
							 | 
						|
								    STRINGS         circuit;
							 | 
						|
								
							 | 
						|
								    RULE*           rules;
							 | 
						|
								
							 | 
						|
								    LAYER_RULES     layer_rules;
							 | 
						|
								
							 | 
						|
								    TOPOLOGY*       topology;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    CLASS( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_class, aParent )
							 | 
						|
								    {
							 | 
						|
								        rules = 0;
							 | 
						|
								        topology = 0;
							 | 
						|
								    }
							 | 
						|
								    ~CLASS()
							 | 
						|
								    {
							 | 
						|
								        delete rules;
							 | 
						|
								        delete topology;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quote = out->GetQuoteChar( class_id.c_str() );
							 | 
						|
								
							 | 
						|
								        int perLine = out->Print( nestLevel, "(%s %s%s%s",
							 | 
						|
								                              Name(),
							 | 
						|
								                              quote, class_id.c_str(), quote );
							 | 
						|
								
							 | 
						|
								        const int RIGHTMARGIN = 72;
							 | 
						|
								
							 | 
						|
								        for( STRINGS::iterator i=net_ids.begin();  i!=net_ids.end();  ++i )
							 | 
						|
								        {
							 | 
						|
								            const char* space = " ";
							 | 
						|
								            if( perLine > RIGHTMARGIN )
							 | 
						|
								            {
							 | 
						|
								                out->Print( 0, "\n" );
							 | 
						|
								                perLine = out->Print( nestLevel+1, "%s", "" );
							 | 
						|
								                space = ""; // no space at first net_id of the line
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            quote = out->GetQuoteChar( i->c_str() );
							 | 
						|
								            perLine += out->Print( 0, "%s%s%s%s", space, quote, i->c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        bool newLine = false;
							 | 
						|
								        if( circuit.size() || rules || layer_rules.size() || topology )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "\n" );
							 | 
						|
								            newLine = true;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( circuit.size() )
							 | 
						|
								        {
							 | 
						|
								            out->Print( nestLevel+1, "(circuit\n" );
							 | 
						|
								            for( STRINGS::iterator i=circuit.begin();  i!=circuit.end();  ++i )
							 | 
						|
								                out->Print( nestLevel+2, "%s\n", i->c_str() );
							 | 
						|
								            out->Print( nestLevel+1, ")\n" );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( rules )
							 | 
						|
								            rules->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        for( LAYER_RULES::iterator i=layer_rules.begin();  i!=layer_rules.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( topology )
							 | 
						|
								            topology->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        out->Print( newLine ? nestLevel : 0, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<CLASS> CLASSLIST;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class NETWORK : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    NETS        nets;
							 | 
						|
								    CLASSLIST   classes;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    NETWORK( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_network, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        for( NETS::iterator i=nets.begin();  i!=nets.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( CLASSLIST::iterator i=classes.begin();  i!=classes.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class CONNECT : public ELEM
							 | 
						|
								{
							 | 
						|
								    // @todo not completed.
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    CONNECT( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_connect, aParent ) {}
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class WIRE
							 | 
						|
								 * corresponds to <wire_shape_descriptor> in the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								class WIRE : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    /*  <shape_descriptor >::=
							 | 
						|
								        [<rectangle_descriptor> |
							 | 
						|
								        <circle_descriptor> |
							 | 
						|
								        <polygon_descriptor> |
							 | 
						|
								        <path_descriptor> |
							 | 
						|
								        <qarc_descriptor> ]
							 | 
						|
								    */
							 | 
						|
								    ELEM*           shape;
							 | 
						|
								
							 | 
						|
								    std::string     net_id;
							 | 
						|
								    int             turret;
							 | 
						|
								    DSN_T           wire_type;
							 | 
						|
								    DSN_T           attr;
							 | 
						|
								    std::string     shield;
							 | 
						|
								    WINDOWS         windows;
							 | 
						|
								    CONNECT*        connect;
							 | 
						|
								    bool            supply;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    WIRE( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_wire, aParent )
							 | 
						|
								    {
							 | 
						|
								        shape = 0;
							 | 
						|
								        connect = 0;
							 | 
						|
								
							 | 
						|
								        turret = -1;
							 | 
						|
								        wire_type = T_NONE;
							 | 
						|
								        attr = T_NONE;
							 | 
						|
								        supply = false;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~WIRE()
							 | 
						|
								    {
							 | 
						|
								        delete shape;
							 | 
						|
								        delete connect;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void SetShape( ELEM* aShape )
							 | 
						|
								    {
							 | 
						|
								        delete shape;
							 | 
						|
								        shape = aShape;
							 | 
						|
								
							 | 
						|
								        if( aShape )
							 | 
						|
								        {
							 | 
						|
								            wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle
							 | 
						|
								                     || aShape->Type()==T_qarc || aShape->Type()==T_path
							 | 
						|
								                     || aShape->Type()==T_polygon);
							 | 
						|
								
							 | 
						|
								            aShape->SetParent( this );
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        out->Print( nestLevel, "(%s ", Name() );
							 | 
						|
								
							 | 
						|
								        if( shape )
							 | 
						|
								            shape->Format( out, 0 );
							 | 
						|
								
							 | 
						|
								        if( net_id.size() )
							 | 
						|
								        {
							 | 
						|
								            const char* quote = out->GetQuoteChar( net_id.c_str() );
							 | 
						|
								            out->Print( 0, "(net %s%s%s)",
							 | 
						|
								                       quote, net_id.c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( turret >= 0 )
							 | 
						|
								            out->Print( 0, "(turrent %d)", turret );
							 | 
						|
								
							 | 
						|
								        if( wire_type != T_NONE )
							 | 
						|
								            out->Print( 0, "(type %s)", GetTokenText( wire_type ) );
							 | 
						|
								
							 | 
						|
								        if( attr != T_NONE )
							 | 
						|
								            out->Print( 0, "(attr %s)", GetTokenText( attr ) );
							 | 
						|
								
							 | 
						|
								        if( shield.size() )
							 | 
						|
								        {
							 | 
						|
								            const char* quote = out->GetQuoteChar( shield.c_str() );
							 | 
						|
								            out->Print( 0, "(shield %s%s%s)",
							 | 
						|
								                       quote, shield.c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( windows.size() )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "\n" );
							 | 
						|
								
							 | 
						|
								            for( WINDOWS::iterator i=windows.begin();  i!=windows.end();  ++i )
							 | 
						|
								                i->Format( out, nestLevel+1 );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( connect )
							 | 
						|
								            connect->Format( out, 0 );
							 | 
						|
								
							 | 
						|
								        if( supply )
							 | 
						|
								            out->Print( 0, "(supply)" );
							 | 
						|
								
							 | 
						|
								        out->Print( 0, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<WIRE>     WIRES;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class WIRE_VIA
							 | 
						|
								 * corresponds to <wire_via_descriptor> in the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								class WIRE_VIA : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     padstack_id;
							 | 
						|
								    POINTS          vertexes;
							 | 
						|
								    std::string     net_id;
							 | 
						|
								    int             via_number;
							 | 
						|
								    DSN_T           via_type;
							 | 
						|
								    DSN_T           attr;
							 | 
						|
								    std::string     virtual_pin_name;
							 | 
						|
								    STRINGS         contact_layers;
							 | 
						|
								    bool            supply;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    WIRE_VIA( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_via, aParent )
							 | 
						|
								    {
							 | 
						|
								        via_number = -1;
							 | 
						|
								        via_type = T_NONE;
							 | 
						|
								        attr = T_NONE;
							 | 
						|
								        supply = false;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    const std::string& GetPadstackId()
							 | 
						|
								    {
							 | 
						|
								        return padstack_id;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quote = out->GetQuoteChar( padstack_id.c_str() );
							 | 
						|
								
							 | 
						|
								        const int RIGHTMARGIN = 80;
							 | 
						|
								        int perLine = out->Print( nestLevel, "(%s %s%s%s",
							 | 
						|
								                       Name(),
							 | 
						|
								                       quote, padstack_id.c_str(), quote );
							 | 
						|
								
							 | 
						|
								        for( POINTS::iterator i=vertexes.begin();  i!=vertexes.end();  ++i )
							 | 
						|
								        {
							 | 
						|
								            if( perLine > RIGHTMARGIN )
							 | 
						|
								            {
							 | 
						|
								                out->Print( 0, "\n" );
							 | 
						|
								                perLine = out->Print( nestLevel+1, "%s", "" );
							 | 
						|
								            }
							 | 
						|
								            else
							 | 
						|
								                perLine += out->Print( 0, "  " );
							 | 
						|
								
							 | 
						|
								            perLine += out->Print( 0, "%.6g %.6g", i->x, i->y );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( net_id.size() || via_number!=-1 || via_type!=T_NONE || attr!=T_NONE || supply)
							 | 
						|
								            out->Print( 0, " " );
							 | 
						|
								
							 | 
						|
								        if( net_id.size() )
							 | 
						|
								        {
							 | 
						|
								            if( perLine > RIGHTMARGIN )
							 | 
						|
								            {
							 | 
						|
								                out->Print( 0, "\n" );
							 | 
						|
								                perLine = out->Print( nestLevel+1, "%s", "" );
							 | 
						|
								            }
							 | 
						|
								            quote = out->GetQuoteChar( net_id.c_str() );
							 | 
						|
								            perLine += out->Print( 0, "(net %s%s%s)", quote, net_id.c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( via_number != -1 )
							 | 
						|
								        {
							 | 
						|
								            if( perLine > RIGHTMARGIN )
							 | 
						|
								            {
							 | 
						|
								                out->Print( 0, "\n" );
							 | 
						|
								                perLine = out->Print( nestLevel+1, "%s", "" );
							 | 
						|
								            }
							 | 
						|
								            perLine += out->Print( 0, "(via_number %d)", via_number );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( via_type != T_NONE )
							 | 
						|
								        {
							 | 
						|
								            if( perLine > RIGHTMARGIN )
							 | 
						|
								            {
							 | 
						|
								                out->Print( 0, "\n" );
							 | 
						|
								                perLine = out->Print( nestLevel+1, "%s", "" );
							 | 
						|
								            }
							 | 
						|
								            perLine += out->Print( 0, "(type %s)", GetTokenText( via_type ) );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( attr != T_NONE )
							 | 
						|
								        {
							 | 
						|
								            if( perLine > RIGHTMARGIN )
							 | 
						|
								            {
							 | 
						|
								                out->Print( 0, "\n" );
							 | 
						|
								                perLine = out->Print( nestLevel+1, "%s", "" );
							 | 
						|
								            }
							 | 
						|
								            if( attr == T_virtual_pin )
							 | 
						|
								            {
							 | 
						|
								                quote = out->GetQuoteChar( virtual_pin_name.c_str() );
							 | 
						|
								                perLine += out->Print( 0, "(attr virtual_pin %s%s%s)",
							 | 
						|
								                           quote, virtual_pin_name.c_str(), quote );
							 | 
						|
								            }
							 | 
						|
								            else
							 | 
						|
								                perLine += out->Print( 0, "(attr %s)", GetTokenText( attr ) );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( supply )
							 | 
						|
								        {
							 | 
						|
								            if( perLine > RIGHTMARGIN )
							 | 
						|
								            {
							 | 
						|
								                out->Print( 0, "\n" );
							 | 
						|
								                perLine = out->Print( nestLevel+1, "%s", "" );
							 | 
						|
								            }
							 | 
						|
								            perLine += out->Print( 0, "(supply)" );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( contact_layers.size() )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "\n" );
							 | 
						|
								            out->Print( nestLevel+1, "(contact\n" );
							 | 
						|
								
							 | 
						|
								            for( STRINGS::iterator i=contact_layers.begin();  i!=contact_layers.end();  ++i )
							 | 
						|
								            {
							 | 
						|
								                quote = out->GetQuoteChar( i->c_str() );
							 | 
						|
								                out->Print( nestLevel+2, "%s%s%s\n", quote, i->c_str(), quote );
							 | 
						|
								            }
							 | 
						|
								            out->Print( nestLevel+1, "))\n" );
							 | 
						|
								        }
							 | 
						|
								        else
							 | 
						|
								            out->Print( 0, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<WIRE_VIA>      WIRE_VIAS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class WIRING
							 | 
						|
								 * corresponds to <wiring_descriptor> in the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								class WIRING : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    UNIT_RES*   unit;
							 | 
						|
								    WIRES       wires;
							 | 
						|
								    WIRE_VIAS   wire_vias;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    WIRING( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_wiring, aParent )
							 | 
						|
								    {
							 | 
						|
								        unit = 0;
							 | 
						|
								    }
							 | 
						|
								    ~WIRING()
							 | 
						|
								    {
							 | 
						|
								        delete unit;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        if( unit )
							 | 
						|
								            unit->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( WIRES::iterator i=wires.begin();  i!=wires.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        for( WIRE_VIAS::iterator i=wire_vias.begin();  i!=wire_vias.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    UNIT_RES*  GetUnits() const
							 | 
						|
								    {
							 | 
						|
								        if( unit )
							 | 
						|
								            return unit;
							 | 
						|
								
							 | 
						|
								        return ELEM::GetUnits();
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class PCB : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     pcbname;
							 | 
						|
								    PARSER*         parser;
							 | 
						|
								    UNIT_RES*       resolution;
							 | 
						|
								    UNIT_RES*       unit;
							 | 
						|
								    STRUCTURE*      structure;
							 | 
						|
								    PLACEMENT*      placement;
							 | 
						|
								    LIBRARY*        library;
							 | 
						|
								    NETWORK*        network;
							 | 
						|
								    WIRING*         wiring;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    PCB( ELEM* aParent = 0 ) :
							 | 
						|
								        ELEM( T_pcb, aParent )
							 | 
						|
								    {
							 | 
						|
								        parser = 0;
							 | 
						|
								        resolution = 0;
							 | 
						|
								        unit = 0;
							 | 
						|
								        structure = 0;
							 | 
						|
								        placement = 0;
							 | 
						|
								        library = 0;
							 | 
						|
								        network = 0;
							 | 
						|
								        wiring = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    ~PCB()
							 | 
						|
								    {
							 | 
						|
								        delete parser;
							 | 
						|
								        delete resolution;
							 | 
						|
								        delete unit;
							 | 
						|
								        delete structure;
							 | 
						|
								        delete placement;
							 | 
						|
								        delete library;
							 | 
						|
								        delete network;
							 | 
						|
								        delete wiring;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quote = out->GetQuoteChar( pcbname.c_str() );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, "(%s %s%s%s\n", Name(),
							 | 
						|
								                                quote, pcbname.c_str(), quote );
							 | 
						|
								
							 | 
						|
								        if( parser )
							 | 
						|
								            parser->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( resolution )
							 | 
						|
								            resolution->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( unit )
							 | 
						|
								            unit->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( structure )
							 | 
						|
								            structure->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( placement )
							 | 
						|
								            placement->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( library )
							 | 
						|
								            library->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( network )
							 | 
						|
								            network->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( wiring )
							 | 
						|
								            wiring->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    UNIT_RES*  GetUnits() const
							 | 
						|
								    {
							 | 
						|
								        if( unit )
							 | 
						|
								            return unit;
							 | 
						|
								
							 | 
						|
								        if( resolution )
							 | 
						|
								            return resolution->GetUnits();
							 | 
						|
								
							 | 
						|
								        return ELEM::GetUnits();
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class ANCESTOR : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     filename;
							 | 
						|
								    std::string     comment;
							 | 
						|
								    time_t          time_stamp;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    ANCESTOR( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_ancestor, aParent )
							 | 
						|
								    {
							 | 
						|
								        time_stamp = time(NULL);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        char    temp[80];
							 | 
						|
								        struct  tm* tmp;
							 | 
						|
								
							 | 
						|
								        tmp = localtime( &time_stamp );
							 | 
						|
								        strftime( temp, sizeof(temp), "%b %d %H : %M : %S %Y", tmp );
							 | 
						|
								
							 | 
						|
								        // format the time first to temp
							 | 
						|
								        // filename may be empty, so quote it just in case.
							 | 
						|
								        out->Print( nestLevel, "(%s \"%s\" (created_time %s)\n",
							 | 
						|
								                     Name(),
							 | 
						|
								                     filename.c_str(),
							 | 
						|
								                     temp );
							 | 
						|
								
							 | 
						|
								        if( comment.size() )
							 | 
						|
								        {
							 | 
						|
								            const char* quote = out->GetQuoteChar( comment.c_str() );
							 | 
						|
								            out->Print( nestLevel+1, "(comment %s%s%s)\n",
							 | 
						|
								                       quote, comment.c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<ANCESTOR>     ANCESTORS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class HISTORY : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    ANCESTORS       ancestors;
							 | 
						|
								    time_t          time_stamp;
							 | 
						|
								    STRINGS         comments;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    HISTORY( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_history, aParent )
							 | 
						|
								    {
							 | 
						|
								        time_stamp = time(NULL);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        for( ANCESTORS::iterator i=ancestors.begin();  i!=ancestors.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        char    temp[80];
							 | 
						|
								        struct  tm* tmp;
							 | 
						|
								
							 | 
						|
								        tmp = localtime( &time_stamp );
							 | 
						|
								        strftime( temp, sizeof(temp), "%b %d %H : %M : %S %Y", tmp );
							 | 
						|
								
							 | 
						|
								        // format the time first to temp
							 | 
						|
								        out->Print( nestLevel, "(self (created_time %s)\n", temp );
							 | 
						|
								
							 | 
						|
								        for( STRINGS::iterator i=comments.begin();  i!=comments.end();  ++i )
							 | 
						|
								        {
							 | 
						|
								            const char* quote = out->GetQuoteChar( i->c_str() );
							 | 
						|
								            out->Print( nestLevel+1, "(comment %s%s%s)\n",
							 | 
						|
								                       quote, i->c_str(), quote );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class SUPPLY_PIN
							 | 
						|
								 * corresponds to the <supply_pin_descriptor> in the specctra dsn spec.
							 | 
						|
								*/
							 | 
						|
								class SUPPLY_PIN : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    PIN_REFS        pin_refs;
							 | 
						|
								    std::string     net_id;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    SUPPLY_PIN( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_supply_pin, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        bool singleLine = pin_refs.size() <= 1;
							 | 
						|
								        out->Print( nestLevel, "(%s", Name() );
							 | 
						|
								
							 | 
						|
								        if( singleLine )
							 | 
						|
								        {
							 | 
						|
								            out->Print( 0, "%s", " " );
							 | 
						|
								            pin_refs.begin()->Format( out, 0 );
							 | 
						|
								        }
							 | 
						|
								        else
							 | 
						|
								        {
							 | 
						|
								            for( PIN_REFS::iterator i=pin_refs.begin();  i!=pin_refs.end();  ++i )
							 | 
						|
								                i->FormatIt( out, nestLevel+1 );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if( net_id.size() )
							 | 
						|
								        {
							 | 
						|
								            const char* newline = singleLine ? "" : "\n";
							 | 
						|
								
							 | 
						|
								            const char* quote = out->GetQuoteChar( net_id.c_str() );
							 | 
						|
								            out->Print( singleLine ? 0 : nestLevel+1,
							 | 
						|
								                       " (net %s%s%s)%s", quote, net_id.c_str(), quote, newline );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        out->Print( singleLine ? 0 : nestLevel, ")\n");
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<SUPPLY_PIN>   SUPPLY_PINS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class NET_OUT
							 | 
						|
								 * corresponds to the <net_out_descriptor> of the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								class NET_OUT : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     net_id;
							 | 
						|
								    int             net_number;
							 | 
						|
								    RULE*           rules;
							 | 
						|
								    WIRES           wires;
							 | 
						|
								    WIRE_VIAS       wire_vias;
							 | 
						|
								    SUPPLY_PINS     supply_pins;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    NET_OUT( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_net_out, aParent )
							 | 
						|
								    {
							 | 
						|
								        rules = 0;
							 | 
						|
								        net_number = -1;
							 | 
						|
								    }
							 | 
						|
								    ~NET_OUT()
							 | 
						|
								    {
							 | 
						|
								        delete rules;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quote = out->GetQuoteChar( net_id.c_str() );
							 | 
						|
								
							 | 
						|
								        // cannot use Type() here, it is T_net_out and we need "(net "
							 | 
						|
								        out->Print( nestLevel, "(net %s%s%s\n",
							 | 
						|
								                   quote, net_id.c_str(), quote );
							 | 
						|
								
							 | 
						|
								        if( net_number>= 0 )
							 | 
						|
								            out->Print( nestLevel+1, "(net_number %d)\n", net_number );
							 | 
						|
								
							 | 
						|
								        if( rules )
							 | 
						|
								            rules->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        for( WIRES::iterator i=wires.begin();  i!=wires.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        for( WIRE_VIAS::iterator i=wire_vias.begin();  i!=wire_vias.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        for( SUPPLY_PINS::iterator i=supply_pins.begin();  i!=supply_pins.end();  ++i )
							 | 
						|
								            i->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								typedef boost::ptr_vector<NET_OUT>      NET_OUTS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class ROUTE : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    UNIT_RES*       resolution;
							 | 
						|
								    PARSER*         parser;
							 | 
						|
								    STRUCTURE_OUT*  structure_out;
							 | 
						|
								    LIBRARY*        library;
							 | 
						|
								    NET_OUTS        net_outs;
							 | 
						|
								//    TEST_POINTS*    test_points;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    ROUTE( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_route, aParent )
							 | 
						|
								    {
							 | 
						|
								        resolution = 0;
							 | 
						|
								        parser = 0;
							 | 
						|
								        structure_out = 0;
							 | 
						|
								        library = 0;
							 | 
						|
								    }
							 | 
						|
								    ~ROUTE()
							 | 
						|
								    {
							 | 
						|
								        delete resolution;
							 | 
						|
								        delete parser;
							 | 
						|
								        delete structure_out;
							 | 
						|
								        delete library;
							 | 
						|
								//        delete test_points;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    UNIT_RES*  GetUnits() const
							 | 
						|
								    {
							 | 
						|
								        if( resolution )
							 | 
						|
								            return resolution;
							 | 
						|
								
							 | 
						|
								        return ELEM::GetUnits();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        if( resolution )
							 | 
						|
								            resolution->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( parser )
							 | 
						|
								            parser->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( structure_out )
							 | 
						|
								            structure_out->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( library )
							 | 
						|
								            library->Format( out, nestLevel );
							 | 
						|
								
							 | 
						|
								        if( net_outs.size() )
							 | 
						|
								        {
							 | 
						|
								            out->Print( nestLevel, "(network_out\n" );
							 | 
						|
								            for( NET_OUTS::iterator i=net_outs.begin();  i!=net_outs.end();  ++i )
							 | 
						|
								                i->Format( out, nestLevel+1 );
							 | 
						|
								            out->Print( nestLevel, ")\n" );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								//        if( test_poinst )
							 | 
						|
								//            test_points->Format( out, nestLevel );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Struct PIN_PAIR
							 | 
						|
								 * is used within the WAS_IS class below to hold a pair of PIN_REFs and
							 | 
						|
								 * corresponds to the (pins was is) construct within the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								struct PIN_PAIR
							 | 
						|
								{
							 | 
						|
								    PIN_PAIR( ELEM* aParent = 0 ) :
							 | 
						|
								        was( aParent ),
							 | 
						|
								        is( aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    PIN_REF     was;
							 | 
						|
								    PIN_REF     is;
							 | 
						|
								};
							 | 
						|
								typedef std::vector<PIN_PAIR>   PIN_PAIRS;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class WAS_IS
							 | 
						|
								 * corresponds to the <was_is_descriptor> in the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								class WAS_IS : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    PIN_PAIRS       pin_pairs;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    WAS_IS( ELEM* aParent ) :
							 | 
						|
								        ELEM( T_was_is, aParent )
							 | 
						|
								    {
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        for( PIN_PAIRS::iterator i=pin_pairs.begin();  i!=pin_pairs.end();  ++i )
							 | 
						|
								        {
							 | 
						|
								            out->Print( nestLevel, "(pins " );
							 | 
						|
								            i->was.Format( out, 0 );
							 | 
						|
								            out->Print( 0, " " );
							 | 
						|
								            i->is.Format( out, 0 );
							 | 
						|
								            out->Print( 0, ")\n" );
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class SESSION
							 | 
						|
								 * corresponds to the <session_file_descriptor> in the specctra dsn spec.
							 | 
						|
								 */
							 | 
						|
								class SESSION : public ELEM
							 | 
						|
								{
							 | 
						|
								    friend class SPECCTRA_DB;
							 | 
						|
								
							 | 
						|
								    std::string     session_id;
							 | 
						|
								    std::string     base_design;
							 | 
						|
								
							 | 
						|
								    HISTORY*        history;
							 | 
						|
								    STRUCTURE*      structure;
							 | 
						|
								    PLACEMENT*      placement;
							 | 
						|
								    WAS_IS*         was_is;
							 | 
						|
								    ROUTE*          route;
							 | 
						|
								
							 | 
						|
								/*  not supported:
							 | 
						|
								    FLOOR_PLAN*         floor_plan;
							 | 
						|
								    NET_PIN_CHANGES*    net_pin_changes;
							 | 
						|
								    SWAP_HISTORY*       swap_history;
							 | 
						|
								*/
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    SESSION( ELEM* aParent = 0 ) :
							 | 
						|
								        ELEM( T_session, aParent )
							 | 
						|
								    {
							 | 
						|
								        history = 0;
							 | 
						|
								        structure = 0;
							 | 
						|
								        placement = 0;
							 | 
						|
								        was_is = 0;
							 | 
						|
								        route = 0;
							 | 
						|
								    }
							 | 
						|
								    ~SESSION()
							 | 
						|
								    {
							 | 
						|
								        delete history;
							 | 
						|
								        delete structure;
							 | 
						|
								        delete placement;
							 | 
						|
								        delete was_is;
							 | 
						|
								        delete route;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IO_ERROR )
							 | 
						|
								    {
							 | 
						|
								        const char* quote = out->GetQuoteChar( session_id.c_str() );
							 | 
						|
								        out->Print( nestLevel, "(%s %s%s%s\n", Name(),
							 | 
						|
								                                quote, session_id.c_str(), quote );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel+1, "(base_design \"%s\")\n", base_design.c_str() );
							 | 
						|
								
							 | 
						|
								        if( history )
							 | 
						|
								            history->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( structure )
							 | 
						|
								            structure->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( placement )
							 | 
						|
								            placement->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( was_is )
							 | 
						|
								            was_is->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        if( route )
							 | 
						|
								            route->Format( out, nestLevel+1 );
							 | 
						|
								
							 | 
						|
								        out->Print( nestLevel, ")\n" );
							 | 
						|
								    }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								typedef boost::ptr_set<PADSTACK>    PADSTACKSET;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Class SPECCTRA_DB
							 | 
						|
								 * holds a DSN data tree, usually coming from a DSN file. Is essentially a
							 | 
						|
								 * SPECCTRA_PARSER class.
							 | 
						|
								 */
							 | 
						|
								class SPECCTRA_DB : public SPECCTRA_LEXER
							 | 
						|
								{
							 | 
						|
								    /// specctra DSN keywords
							 | 
						|
								    static const KEYWORD keywords[];
							 | 
						|
								    static const unsigned keywordCount;
							 | 
						|
								
							 | 
						|
								    PCB*            pcb;
							 | 
						|
								    SESSION*        session;
							 | 
						|
								    wxString        filename;
							 | 
						|
								    std::string     quote_char;
							 | 
						|
								
							 | 
						|
								    bool            modulesAreFlipped;
							 | 
						|
								
							 | 
						|
								    STRING_FORMATTER sf;
							 | 
						|
								
							 | 
						|
								    STRINGS         layerIds;       ///< indexed by PCB layer number
							 | 
						|
								
							 | 
						|
								    /// maps BOARD layer number to PCB layer numbers
							 | 
						|
								    std::vector<int> kicadLayer2pcb;
							 | 
						|
								
							 | 
						|
								    /// maps PCB layer number to BOARD layer numbers
							 | 
						|
								    std::vector<LAYER_ID>   pcbLayer2kicad;
							 | 
						|
								
							 | 
						|
								    /// used during FromSESSION() only, memory for it is not owned here.
							 | 
						|
								    UNIT_RES*       routeResolution;
							 | 
						|
								
							 | 
						|
								    /// a copy to avoid passing as an argument, memory for it is not owned here.
							 | 
						|
								    BOARD*          sessionBoard;
							 | 
						|
								
							 | 
						|
								    static const KICAD_T scanPADs[];
							 | 
						|
								
							 | 
						|
								    PADSTACKSET     padstackset;
							 | 
						|
								
							 | 
						|
								    /// we don't want ownership here permanently, so we don't use boost::ptr_vector
							 | 
						|
								    std::vector<NET*>   nets;
							 | 
						|
								
							 | 
						|
								    /// specctra cu layers, 0 based index:
							 | 
						|
								    int     m_top_via_layer;
							 | 
						|
								    int     m_bot_via_layer;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function buildLayerMaps
							 | 
						|
								     * creates a few data translation structures for layer name and number
							 | 
						|
								     * mapping between the DSN::PCB structure and the KiCad BOARD structure.
							 | 
						|
								     * @param aBoard The BOARD to create the maps for.
							 | 
						|
								     */
							 | 
						|
								    void buildLayerMaps( BOARD* aBoard );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function findLayerName
							 | 
						|
								     * returns the PCB layer index for a given layer name, within the specctra session
							 | 
						|
								     * file.
							 | 
						|
								     *
							 | 
						|
								     * @return int - the layer index within the specctra session file, or -1 if
							 | 
						|
								     *  aLayerName is not found.
							 | 
						|
								     */
							 | 
						|
								    int findLayerName( const std::string& aLayerName ) const;
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function readCOMPnPIN
							 | 
						|
								     * reads a <pin_reference> and splits it into the two parts which are
							 | 
						|
								     * on either side of the hyphen.  This function is specialized because
							 | 
						|
								     * pin_reference may or may not be using double quotes.  Both of these
							 | 
						|
								     * are legal:  U2-14 or "U2"-"14".  The lexer treats the first one as a
							 | 
						|
								     * single T_SYMBOL, so in that case we have to split it into two here.
							 | 
						|
								     * <p>
							 | 
						|
								     * The caller should have already read in the first token comprizing the
							 | 
						|
								     * pin_reference and it will be tested through CurTok().
							 | 
						|
								     *
							 | 
						|
								     * @param component_id Where to put the text preceeding the '-' hyphen.
							 | 
						|
								     * @param pid_id Where to put the text which trails the '-'.
							 | 
						|
								     * @throw IO_ERROR, if the next token or two do no make up a pin_reference,
							 | 
						|
								     * or there is an error reading from the input stream.
							 | 
						|
								     */
							 | 
						|
								    void readCOMPnPIN( std::string* component_id, std::string* pid_id ) throw( IO_ERROR );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function readTIME
							 | 
						|
								     * reads a <time_stamp> which consists of 8 lexer tokens:
							 | 
						|
								     * "month date hour : minute : second year".
							 | 
						|
								     * This function is specialized because time_stamps occur more than
							 | 
						|
								     * once in a session file.
							 | 
						|
								     * <p>
							 | 
						|
								     * The caller should not have already read in the first token comprizing the
							 | 
						|
								     * time stamp.
							 | 
						|
								     *
							 | 
						|
								     * @param time_stamp Where to put the parsed time value.
							 | 
						|
								     * @throw IO_ERROR, if the next token or 8 do no make up a time stamp,
							 | 
						|
								     * or there is an error reading from the input stream.
							 | 
						|
								     */
							 | 
						|
								    void readTIME( time_t* time_stamp ) throw( IO_ERROR );
							 | 
						|
								
							 | 
						|
								    void doPCB( PCB* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doPARSER( PARSER* growth ) throw( IO_ERROR );
							 | 
						|
								    void doRESOLUTION( UNIT_RES* growth ) throw( IO_ERROR );
							 | 
						|
								    void doUNIT( UNIT_RES* growth ) throw( IO_ERROR );
							 | 
						|
								    void doSTRUCTURE( STRUCTURE* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doSTRUCTURE_OUT( STRUCTURE_OUT* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doLAYER_NOISE_WEIGHT( LAYER_NOISE_WEIGHT* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doLAYER_PAIR( LAYER_PAIR* growth ) throw( IO_ERROR );
							 | 
						|
								    void doBOUNDARY( BOUNDARY* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doRECTANGLE( RECTANGLE* growth ) throw( IO_ERROR );
							 | 
						|
								    void doPATH( PATH* growth ) throw( IO_ERROR );
							 | 
						|
								    void doSTRINGPROP( STRINGPROP* growth ) throw( IO_ERROR );
							 | 
						|
								    void doTOKPROP( TOKPROP* growth ) throw( IO_ERROR );
							 | 
						|
								    void doVIA( VIA* growth ) throw( IO_ERROR );
							 | 
						|
								    void doCONTROL( CONTROL* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doLAYER( LAYER* growth ) throw( IO_ERROR );
							 | 
						|
								    void doRULE( RULE* growth ) throw( IO_ERROR );
							 | 
						|
								    void doKEEPOUT( KEEPOUT* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doCIRCLE( CIRCLE* growth ) throw( IO_ERROR );
							 | 
						|
								    void doQARC( QARC* growth ) throw( IO_ERROR );
							 | 
						|
								    void doWINDOW( WINDOW* growth ) throw( IO_ERROR );
							 | 
						|
								    void doCONNECT( CONNECT* growth ) throw( IO_ERROR );
							 | 
						|
								    void doREGION( REGION* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doCLASS_CLASS( CLASS_CLASS* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doLAYER_RULE( LAYER_RULE* growth ) throw( IO_ERROR );
							 | 
						|
								    void doCLASSES( CLASSES* growth ) throw( IO_ERROR );
							 | 
						|
								    void doGRID( GRID* growth ) throw( IO_ERROR );
							 | 
						|
								    void doPLACE( PLACE* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doCOMPONENT( COMPONENT* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doPLACEMENT( PLACEMENT* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doPROPERTIES( PROPERTIES* growth ) throw( IO_ERROR );
							 | 
						|
								    void doPADSTACK( PADSTACK* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doSHAPE( SHAPE* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doIMAGE( IMAGE* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doLIBRARY( LIBRARY* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doPIN( PIN* growth ) throw( IO_ERROR );
							 | 
						|
								    void doNET( NET* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doNETWORK( NETWORK* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doCLASS( CLASS* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doTOPOLOGY( TOPOLOGY* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doFROMTO( FROMTO* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doCOMP_ORDER( COMP_ORDER* growth ) throw( IO_ERROR );
							 | 
						|
								    void doWIRE( WIRE* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doWIRE_VIA( WIRE_VIA* growth ) throw( IO_ERROR );
							 | 
						|
								    void doWIRING( WIRING* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doSESSION( SESSION* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doANCESTOR( ANCESTOR* growth ) throw( IO_ERROR );
							 | 
						|
								    void doHISTORY( HISTORY* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doROUTE( ROUTE* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doWAS_IS( WAS_IS* growth ) throw( IO_ERROR );
							 | 
						|
								    void doNET_OUT( NET_OUT* growth ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								    void doSUPPLY_PIN( SUPPLY_PIN* growth ) throw( IO_ERROR );
							 | 
						|
								
							 | 
						|
								    //-----<FromBOARD>-------------------------------------------------------
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function fillBOUNDARY
							 | 
						|
								     * makes the board perimeter for the DSN file by filling the BOUNDARY element
							 | 
						|
								     * in the specctra element tree.
							 | 
						|
								     * @param aBoard The BOARD to get information from in order to make the BOUNDARY.
							 | 
						|
								     * @param aBoundary The empty BOUNDARY to fill in.
							 | 
						|
								     */
							 | 
						|
								    void fillBOUNDARY( BOARD* aBoard, BOUNDARY* aBoundary ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function makeIMAGE
							 | 
						|
								     * allocates an IMAGE on the heap and creates all the PINs according
							 | 
						|
								     * to the D_PADs in the MODULE.
							 | 
						|
								     * @param aBoard The owner of the MODULE.
							 | 
						|
								     * @param aModule The MODULE from which to build the IMAGE.
							 | 
						|
								     * @return IMAGE* - not tested for duplication yet.
							 | 
						|
								     */
							 | 
						|
								    IMAGE* makeIMAGE( BOARD* aBoard, MODULE* aModule );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function makePADSTACK
							 | 
						|
								     * creates a PADSTACK which matches the given pad.  Only pads which do not
							 | 
						|
								     * satisfy the function isKeepout() should be passed to this function.
							 | 
						|
								     * @param aBoard The owner of the MODULE.
							 | 
						|
								     * @param aPad The D_PAD which needs to be made into a PADSTACK.
							 | 
						|
								     * @return PADSTACK* - The created padstack, including its padstack_id.
							 | 
						|
								     */
							 | 
						|
								    PADSTACK* makePADSTACK( BOARD* aBoard, D_PAD* aPad );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function makeVia
							 | 
						|
								     * makes a round through hole PADSTACK using the given KiCad diameter in deci-mils.
							 | 
						|
								     * @param aCopperDiameter The diameter of the copper pad.
							 | 
						|
								     * @param aDrillDiameter The drill diameter, used on re-import of the session file.
							 | 
						|
								     * @param aTopLayer The DSN::PCB top most layer index.
							 | 
						|
								     * @param aBotLayer The DSN::PCB bottom most layer index.
							 | 
						|
								     * @return PADSTACK* - The padstack, which is on the heap only, user must save
							 | 
						|
								     *  or delete it.
							 | 
						|
								     */
							 | 
						|
								    PADSTACK* makeVia( int aCopperDiameter, int aDrillDiameter,
							 | 
						|
								                       int aTopLayer, int aBotLayer );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function makeVia
							 | 
						|
								     * makes any kind of PADSTACK using the given KiCad VIA.
							 | 
						|
								     * @param aVia The VIA to build the padstack from.
							 | 
						|
								     * @return PADSTACK* - The padstack, which is on the heap only, user must save
							 | 
						|
								     *  or delete it.
							 | 
						|
								     */
							 | 
						|
								    PADSTACK* makeVia( const ::VIA* aVia );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function deleteNETs
							 | 
						|
								     * deletes all the NETs that may be in here.
							 | 
						|
								     */
							 | 
						|
								    void deleteNETs()
							 | 
						|
								    {
							 | 
						|
								        for( unsigned n=0;  n<nets.size();  ++n )
							 | 
						|
								            delete nets[n];
							 | 
						|
								
							 | 
						|
								        nets.clear();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function exportNETCLASS
							 | 
						|
								     * exports \a aNetClass to the DSN file.
							 | 
						|
								     */
							 | 
						|
								    void exportNETCLASS( boost::shared_ptr<NETCLASS> aNetClass, BOARD* aBoard );
							 | 
						|
								
							 | 
						|
								    //-----</FromBOARD>------------------------------------------------------
							 | 
						|
								
							 | 
						|
								    //-----<FromSESSION>-----------------------------------------------------
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function makeTRACK
							 | 
						|
								     * creates a TRACK form the PATH and BOARD info.
							 | 
						|
								     */
							 | 
						|
								    TRACK* makeTRACK( PATH* aPath, int aPointIndex, int aNetcode ) throw( IO_ERROR );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function makeVIA
							 | 
						|
								     * instantiates a KiCad VIA on the heap and initializes it with internal
							 | 
						|
								     * values consistent with the given PADSTACK, POINT, and netcode.
							 | 
						|
								     */
							 | 
						|
								    ::VIA* makeVIA( PADSTACK* aPadstack, const POINT& aPoint, int aNetCode, int aViaDrillDefault )
							 | 
						|
								        throw( IO_ERROR );
							 | 
						|
								
							 | 
						|
								    //-----</FromSESSION>----------------------------------------------------
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								
							 | 
						|
								    SPECCTRA_DB() :
							 | 
						|
								        SPECCTRA_LEXER( 0 )         // LINE_READER* == NULL, no DSNLEXER::PushReader()
							 | 
						|
								    {
							 | 
						|
								        // The LINE_READER will be pushed from an automatic instantiation,
							 | 
						|
								        // we don't own it:
							 | 
						|
								        wxASSERT( !iOwnReaders );
							 | 
						|
								
							 | 
						|
								        pcb   = 0;
							 | 
						|
								        session = 0;
							 | 
						|
								        quote_char += '"';
							 | 
						|
								        modulesAreFlipped = false;
							 | 
						|
								
							 | 
						|
								        SetSpecctraMode( true );
							 | 
						|
								
							 | 
						|
								        // Avoid not initialized members:
							 | 
						|
								        routeResolution = NULL;
							 | 
						|
								        sessionBoard = NULL;
							 | 
						|
								        m_top_via_layer = 0;
							 | 
						|
								        m_bot_via_layer = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    virtual ~SPECCTRA_DB()
							 | 
						|
								    {
							 | 
						|
								        delete pcb;
							 | 
						|
								        delete session;
							 | 
						|
								
							 | 
						|
								        deleteNETs();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function MakePCB
							 | 
						|
								     * makes a PCB with all the default ELEMs and parts on the heap.
							 | 
						|
								     */
							 | 
						|
								    static PCB* MakePCB();
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function SetPCB
							 | 
						|
								     * deletes any existing PCB and replaces it with the given one.
							 | 
						|
								     */
							 | 
						|
								    void SetPCB( PCB* aPcb )
							 | 
						|
								    {
							 | 
						|
								        delete pcb;
							 | 
						|
								        pcb = aPcb;
							 | 
						|
								    }
							 | 
						|
								    PCB*  GetPCB()  { return pcb; }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function SetSESSION
							 | 
						|
								     * deletes any existing SESSION and replaces it with the given one.
							 | 
						|
								     */
							 | 
						|
								    void SetSESSION( SESSION* aSession )
							 | 
						|
								    {
							 | 
						|
								        delete session;
							 | 
						|
								        session = aSession;
							 | 
						|
								    }
							 | 
						|
								    SESSION* GetSESSION() { return session; }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function LoadPCB
							 | 
						|
								     * is a recursive descent parser for a SPECCTRA DSN "design" file.
							 | 
						|
								     * A design file is nearly a full description of a PCB (seems to be
							 | 
						|
								     * missing only the silkscreen stuff).
							 | 
						|
								     *
							 | 
						|
								     * @param filename The name of the dsn file to load.
							 | 
						|
								     * @throw IO_ERROR if there is a lexer or parser error.
							 | 
						|
								     */
							 | 
						|
								    void LoadPCB( const wxString& filename ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function LoadSESSION
							 | 
						|
								     * is a recursive descent parser for a SPECCTRA DSN "session" file.
							 | 
						|
								     * A session file is a file that is fed back from the router to the layout
							 | 
						|
								     * tool (Pcbnew) and should be used to update a BOARD object with the new
							 | 
						|
								     * tracks, vias, and component locations.
							 | 
						|
								     *
							 | 
						|
								     * @param aFilename The name of the dsn file to load.
							 | 
						|
								     * @throw IO_ERROR if there is a lexer or parser error.
							 | 
						|
								     */
							 | 
						|
								    void LoadSESSION( const wxString& aFilename ) throw( IO_ERROR, boost::bad_pointer );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function ExportPCB
							 | 
						|
								     * writes the internal PCB instance out as a SPECTRA DSN format file.
							 | 
						|
								     *
							 | 
						|
								     * @param aFilename The file to save to.
							 | 
						|
								     * @param aNameChange If true, causes the pcb's name to change to "aFilename"
							 | 
						|
								     *          and also to to be changed in the output file.
							 | 
						|
								     * @throw IO_ERROR, if an i/o error occurs saving the file.
							 | 
						|
								     */
							 | 
						|
								    void ExportPCB( wxString aFilename,  bool aNameChange=false ) throw( IO_ERROR );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function FromBOARD
							 | 
						|
								     * adds the entire BOARD to the PCB but does not write it out.  Note that
							 | 
						|
								     * the BOARD given to this function must have all the MODULEs on the component
							 | 
						|
								     * side of the BOARD.
							 | 
						|
								     *
							 | 
						|
								     * See void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event )
							 | 
						|
								     * for how this can be done before calling this function.
							 | 
						|
								     *
							 | 
						|
								     * @param aBoard The BOARD to convert to a PCB.
							 | 
						|
								     */
							 | 
						|
								    void FromBOARD( BOARD* aBoard ) throw( IO_ERROR, boost::bad_ptr_container_operation );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function FromSESSION
							 | 
						|
								     * adds the entire SESSION info to a BOARD but does not write it out.  The
							 | 
						|
								     * the BOARD given to this function will have all its tracks and via's replaced,
							 | 
						|
								     * and all its components are subject to being moved.
							 | 
						|
								     *
							 | 
						|
								     * @param aBoard The BOARD to merge the SESSION information into.
							 | 
						|
								     */
							 | 
						|
								    void FromSESSION( BOARD* aBoard ) throw( IO_ERROR );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function ExportSESSION
							 | 
						|
								     * writes the internal SESSION instance out as a SPECTRA DSN format file.
							 | 
						|
								     *
							 | 
						|
								     * @param aFilename The file to save to.
							 | 
						|
								     */
							 | 
						|
								    void ExportSESSION( wxString aFilename );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function FlipMODULEs
							 | 
						|
								     * flips the modules which are on the back side of the board to the front.
							 | 
						|
								     */
							 | 
						|
								    void FlipMODULEs( BOARD* aBoard );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function RevertMODULEs
							 | 
						|
								     * flips the modules which were on the back side of the board back to the back.
							 | 
						|
								     */
							 | 
						|
								    void RevertMODULEs( BOARD* aBoard );
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Function GetBoardPolygonOutlines
							 | 
						|
								     * Is not used in SPECCTRA export, but uses a lot of functions from it
							 | 
						|
								     * and is used to extract a board outlines (3D view, automatic zones build ...)
							 | 
						|
								     * makes the board perimeter by filling the BOUNDARY element
							 | 
						|
								     * any closed outline inside the main outline is a hole
							 | 
						|
								     * All contours should be closed, i.e. have valid vertices to build a closed polygon
							 | 
						|
								     * @param aBoard The BOARD to get information from in order to make the outlines.
							 | 
						|
								     * @param aOutlines The SHAPE_POLY_SET to fill in with main outlines.
							 | 
						|
								     * @param aHoles The empty SHAPE_POLY_SET to fill in with holes, if any.
							 | 
						|
								     * @param aErrorText = a wxString reference to display an error message
							 | 
						|
								     *          with the coordinate of the point which creates the error
							 | 
						|
								     *          (default = NULL , no message returned on error)
							 | 
						|
								     * @return true if success, false if a contour is not valid
							 | 
						|
								     */
							 | 
						|
								    bool GetBoardPolygonOutlines( BOARD* aBoard,
							 | 
						|
								                                  SHAPE_POLY_SET& aOutlines,
							 | 
						|
								                                  SHAPE_POLY_SET& aHoles,
							 | 
						|
								                                  wxString* aErrorText = NULL );
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								}           // namespace DSN
							 | 
						|
								
							 | 
						|
								#endif      // SPECCTRA_H_
							 | 
						|
								
							 | 
						|
								//EOF
							 |