Commit 67ebe29b authored by dickelbeck's avatar dickelbeck
Browse files

more free specctra work

parent 7878ba27
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line


Change Log for Kicad
Started 2007-June-11

@@ -16,7 +15,6 @@ email address.
	the new track takes the width of the existing track



2008-Jan-27 UPDATE   Dick Hollenbeck <dick@softplc.com>
================================================================================
+all:
+146 −14
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@
#include <wx/ffile.h>


// To build the DSN beautifier and unit tester, simply uncomment this and then
// use CMake's makefile to build target "specctra_test".
//#define STANDALONE        // define "stand alone, i.e. unit testing"


@@ -861,24 +863,32 @@ void SPECCTRA_DB::doWINDOW( WINDOW* growth ) throw( IOError )
        switch( tok )
        {
        case T_rect:
            growth->rectangle = new RECTANGLE( growth );
            doRECTANGLE( growth->rectangle );
            if( growth->shape )
                unexpected( tok );
            growth->shape = new RECTANGLE( growth );
            doRECTANGLE( (RECTANGLE*) growth->shape );
            break;
            
        case T_circle:
            growth->circle = new CIRCLE( growth );
            doCIRCLE( growth->circle );
            if( growth->shape )
                unexpected( tok );
            growth->shape = new CIRCLE( growth );
            doCIRCLE( (CIRCLE*) growth->shape );
            break;
            
        case T_path:
        case T_polygon:
            growth->path = new PATH( growth, tok );
            doPATH( growth->path );
            if( growth->shape )
                unexpected( tok );
            growth->shape = new PATH( growth, tok );
            doPATH( (PATH*) growth->shape );
            break;
            
        case T_qarc:
            growth->qarc = new QARC( growth );
            doQARC( growth->qarc );
            if( growth->shape )
                unexpected( tok );
            growth->shape = new QARC( growth );
            doQARC( (QARC*) growth->shape );
            break;
            
        default:
@@ -3353,18 +3363,19 @@ int SPECCTRA_DB::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
    return total;
}

// factor out a common GetQuoteChar

const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee ) 
const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote_char ) 
{
    // I include '#' so a symbol is not confused with a comment.  We intend
    // to wrap any symbol starting with a '#'.
    // Our LEXER class handles comments, and comments appear to be an extension
    // to the SPECCTRA DSN specification. 
    if( *wrapee == '#' )
        return quote_char.c_str();
        return quote_char;

    if( strlen(wrapee)==0 )
        return quote_char.c_str();
        return quote_char;
        
    bool    isNumber = true;
    
@@ -3373,19 +3384,25 @@ const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee )
        // if the string to be wrapped (wrapee) has a delimiter in it, 
        // return the quote_char so caller wraps the wrapee.
        if( strchr( "\t ()", *wrapee ) )
            return quote_char.c_str();
            return quote_char;
        
        if( !strchr( "01234567890.-+", *wrapee ) )
            isNumber = false;
    }
    
    if( isNumber )
        return quote_char.c_str();
        return quote_char;
    
    return "";      // can use an unwrapped string.
}


const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee ) 
{
    return OUTPUTFORMATTER::GetQuoteChar( wrapee, quote_char.c_str() ); 
}


void SPECCTRA_DB::ExportPCB( wxString filename, bool aNameChange ) throw( IOError )
{
    fp = wxFopen( filename, wxT("w") );
@@ -3438,6 +3455,8 @@ PCB* SPECCTRA_DB::MakePCB()
    
    pcb->structure = new STRUCTURE( pcb );
    pcb->structure->boundary = new BOUNDARY( pcb->structure );
    pcb->structure->via = new VIA( pcb->structure );
    pcb->structure->rules = new RULE( pcb->structure, T_rule );
    
    pcb->placement = new PLACEMENT( pcb );
    
@@ -3451,6 +3470,87 @@ PCB* SPECCTRA_DB::MakePCB()
}


//-----<STRINGFORMATTER>----------------------------------------------------

const char* STRINGFORMATTER::GetQuoteChar( const char* wrapee ) 
{
    // for what we are using STRINGFORMATTER for at this time, we can return the nul string
    // always.
    
    return "";
//    return OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, "\"" ); 
}

int STRINGFORMATTER::vprint( const char* fmt,  va_list ap )
{
    int ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
    if( ret >= (int) buffer.size() )
    {
        buffer.reserve( ret+200 );
        ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
    }
    
    if( ret > 0 )
        mystring.append( (const char*) &buffer[0] );
    
    return ret;
}    


int STRINGFORMATTER::sprint( const char* fmt, ... )
{
    va_list     args;

    va_start( args, fmt );
    int ret = vprint( fmt, args);
    va_end( args );
    
    return ret;
}    


int STRINGFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
{
    va_list     args;

    va_start( args, fmt );
    
    int result = 0;
    int total  = 0;
    
    for( int i=0; i<nestLevel;  ++i )
    {
        result = sprint( "%*c", NESTWIDTH, ' ' );
        if( result < 0 )
            break;
        
        total += result;
    }
    
    if( result<0 || (result=vprint( fmt, args ))<0 )
    {
        throw IOError( _("Error writing to STRINGFORMATTER") );
    }
    
    va_end( args );
    
    total += result;
    return total;
}


void STRINGFORMATTER::StripUseless()
{
    for( std::string::iterator i=mystring.begin();  i!=mystring.end();  )
    {
        if( isspace( *i ) || *i==')' || *i=='(' )
            mystring.erase(i);
        else
            ++i;
    }
}


//-----<ELEM>---------------------------------------------------------------

ELEM::ELEM( DSN_T aType, ELEM* aParent ) :
@@ -3500,8 +3600,40 @@ int ELEM_HOLDER::FindElem( DSN_T aType, int instanceNum )
}


//-----<PARSER>-----------------------------------------------------------
//-----<PADSTACK>---------------------------------------------------------

int PADSTACK::Compare( PADSTACK* lhs, PADSTACK* rhs )
{
    if( !lhs->hash.size() )
        lhs->hash = lhs->makeHash();
    
    if( !rhs->hash.size() )
        rhs->hash = rhs->makeHash();
    
    int result = lhs->hash.compare( rhs->hash );
    return result;
}


//-----<IMAGE>------------------------------------------------------------

int IMAGE::Compare( IMAGE* lhs, IMAGE* rhs )
{
    if( !lhs->hash.size() )
        lhs->hash = lhs->makeHash();
    
    if( !rhs->hash.size() )
        rhs->hash = rhs->makeHash();

    int result = lhs->hash.compare( rhs->hash );
    
    // printf("\"%s\"  \"%s\" ret=%d\n", lhs->hash.c_str(), rhs->hash.c_str(), result );
    
    return result;
}


//-----<PARSER>-----------------------------------------------------------

PARSER::PARSER( ELEM* aParent ) :
    ELEM( T_parser, aParent )
+303 −95
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@
#include "fctsys.h"
#include "dsn.h"

class TYPE_COLLECTOR;           // outside the DSN namespace



/**
@@ -101,9 +103,86 @@ public:
     *   if the wrapee does not need to be wrapped.
     */
    virtual const char* GetQuoteChar( const char* wrapee ) = 0;

    virtual ~OUTPUTFORMATTER() {}

    /**
     * Function GetQuoteChar
     * factor may be used by derived classes to perform quote character selection.
     * @param wrapee A string that might need wrapping on each end.
     * @param quote_char A single character C string which hold the current quote character.
     * @return const char* - the quote_char as a single character string, or ""
     *   if the wrapee does not need to be wrapped.
     */
    static const char* GetQuoteChar( const char* wrapee, const char* quote_char ); 
};


/**
 * Class STRINGFORMATTER
 * implements OUTPUTFORMATTER to a memory buffer.  After Print()ing the
 * string is available through GetString()
*/ 
class STRINGFORMATTER : public OUTPUTFORMATTER
{
    std::vector<char>       buffer;
    std::string             mystring;
    
    int sprint( const char* fmt, ... );
    int vprint( const char* fmt,  va_list ap );

public:

    /**
     * Constructor STRINGFORMATTER
     * reserves space in the buffer
     */
    STRINGFORMATTER( int aReserve = 300 ) :
        buffer( aReserve, '\0' )
    {
    }

    
    /**
     * Function Clear
     * clears the buffer and empties the internal string.
     */
    void Clear()
    {
        mystring.clear();
    }

    /**
     * Function StripUseless
     * removes whitespace, '(', and ')' from the mystring.
     */
    void StripUseless();

    /*    
    const char* c_str()
    {
        return mystring.c_str(); 
    }
    */

    std::string GetString()
    {
        return mystring;
    }
    
    
    //-----<OUTPUTFORMATTER>------------------------------------------------    
    int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError );
    const char* GetQuoteChar( const char* wrapee );
    //-----</OUTPUTFORMATTER>-----------------------------------------------    
};


/**
 * Class 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;
@@ -136,14 +215,23 @@ struct POINT
    POINT& operator=( const POINT& other )
    {
        x = other.x;
        if( x == -0.0 )     // correct -0.0 so output looks nice.
            x = 0.0;
        y = other.y;
        if( y == -0.0 )
            y = 0.0;
        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 mantiss and exponent
     * would say the value is zero.
     */
    void FixNegativeZero()
    {
        if( x == -0.0 )
            x = 0.0;
        if( y == -0.0 )
            y = 0.0;
    }
    
    /**
     * Function Format
@@ -197,17 +285,40 @@ 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()
    {
        STRINGFORMATTER sf;
        
        FormatContents( &sf, 0 );
        sf.StripUseless();
        
        return sf.GetString();
    }

    
public:

    ELEM( DSN_T aType, ELEM* aParent = 0 );
    
    virtual ~ELEM();
    
    DSN_T   Type() { return type; }
    DSN_T   Type() const { return type; }

    
    /**
@@ -216,7 +327,7 @@ public:
     * to check for section specific overrides.
     * @return DSN_T - one of the allowed values to &lt;unit_descriptor&gt;
     */
    virtual DSN_T   GetUnits()
    virtual DSN_T   GetUnits() const
    {
        if( parent )
            return parent->GetUnits();
@@ -324,14 +435,14 @@ public:
        kids.insert( kids.begin()+aIndex, aElem );
    }
    
    ELEM*   At( int aIndex )
    ELEM*   At( int aIndex ) const
    {
        // we have varying sized objects and are using polymorphism, so we
        // must return a pointer not a reference.
        return &kids[aIndex];
        return (ELEM*) &kids[aIndex];
    }
    
    ELEM* operator[]( int aIndex )
    ELEM* operator[]( int aIndex ) const
    {
        return At( aIndex );
    }
@@ -408,7 +519,7 @@ public:
                       LEXER::GetTokenText(units), value ); 
    }
    
    DSN_T   GetUnits()
    DSN_T   GetUnits() const
    {
        return units;
    }
@@ -439,7 +550,10 @@ public:
    void SetCorners( const POINT& aPoint0, const POINT& aPoint1 )
    {
        point0 = aPoint0;
        point0.FixNegativeZero();        
        
        point1 = aPoint1;
        point1.FixNegativeZero();        
    }
    
    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
@@ -581,7 +695,6 @@ public:
        out->Print( nestLevel, ")\n" );
    }
};

typedef boost::ptr_vector<LAYER_RULE>   LAYER_RULES;


@@ -781,14 +894,20 @@ public:
    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();
    }
};

@@ -797,49 +916,53 @@ class WINDOW : public ELEM
{
    friend class SPECCTRA_DB;

    //----- only one of these is used, like a union -----
protected:    
    /*  shape holds one of these
    PATH*           path;           ///< used for both path and polygon
    RECTANGLE*      rectangle;
    CIRCLE*         circle;
    QARC*           qarc;
    //---------------------------------------------------
    */
    ELEM*       shape;
    
public:
    
    WINDOW( ELEM* aParent ) :
        ELEM( T_window, aParent )
    WINDOW( ELEM* aParent, DSN_T aType = T_window ) :
        ELEM( aType, aParent )
    {
        path = 0;
        rectangle = 0;
        circle = 0;
        qarc = 0;
        shape = 0;
    }
    
    ~WINDOW()
    {
        delete path;
        delete rectangle;
        delete circle;
        delete qarc;
        delete shape;
    }

    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    void SetShape( ELEM* aShape )
    {
        // these are mutually exclusive
        if( rectangle )
            rectangle->Format( out, nestLevel );
        delete shape;
        shape = aShape;
        
        else if( path )
            path->Format( out, nestLevel );
        if( aShape )
        {
            wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle 
                     || aShape->Type()==T_qarc || aShape->Type()==T_path 
                     || aShape->Type()==T_polygon);
            
        else if( circle )
            circle->Format( out, nestLevel );
            aShape->SetParent( this );            
        }
    }

        else if( qarc )
            qarc->Format( out, nestLevel );
    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        out->Print( nestLevel, "(%s ", LEXER::GetTokenText( Type() ) );
        
        if( shape )
            shape->Format( out, 0 );
        
        out->Print( 0, ")\n" );
    }
};

typedef boost::ptr_vector<WINDOW>   WINDOWS;


@@ -957,6 +1080,11 @@ public:
    {
    }

    void AppendVia( const char* aViaName )
    {
        padstacks.push_back( aViaName );
    }
    
    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        const int RIGHTMARGIN = 80;
@@ -1217,13 +1345,13 @@ public:
               layer_weight );
    }
};
typedef boost::ptr_vector<LAYER_PAIR>  LAYER_PAIRS;


class LAYER_NOISE_WEIGHT : public ELEM
{
    friend class SPECCTRA_DB;
    
    typedef boost::ptr_vector<LAYER_PAIR>  LAYER_PAIRS;
    LAYER_PAIRS     layer_pairs;
    
public:
@@ -1542,7 +1670,7 @@ public:
            i->Format( out, nestLevel );
    }
    
    DSN_T   GetUnits()
    DSN_T   GetUnits() const
    {
        if( unit )
            return unit->GetUnits();
@@ -1693,7 +1821,7 @@ public:
            i->Format( out, nestLevel );
    }
    
    DSN_T   GetUnits()
    DSN_T   GetUnits() const
    {
        if( unit )
            return unit->GetUnits();
@@ -1710,7 +1838,7 @@ public:
 * elements contains, i.e. in its "shape" field.  This class also implements
 * the "(outline ...)" element as a dual personality.
 */
class SHAPE : public ELEM
class SHAPE : public WINDOW
{
    friend class SPECCTRA_DB;

@@ -1722,36 +1850,16 @@ class SHAPE : public ELEM
        <polygon_descriptor> |
        <path_descriptor> |
        <qarc_descriptor> ]
    ELEM*           shape;      // inherited from WINDOW
    */
    ELEM*           shape;

    WINDOWS         windows;
    
public:
    SHAPE( ELEM* aParent, DSN_T aType = T_shape ) :
        ELEM( aType, aParent )
        WINDOW( aParent, aType )
    {
        connect = T_on;
        shape = 0;
    }
    ~SHAPE()
    {
        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 SetConnect( DSN_T aConnect )
@@ -1808,6 +1916,12 @@ public:
        isRotated = (aRotation != 0.0);
    }
    
    void SetVertex( const POINT& aPoint )
    {
        vertex = aPoint;
        vertex.FixNegativeZero();        
    }
    
    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        const char* quote = out->GetQuoteChar( padstack_id.c_str() );
@@ -1830,6 +1944,8 @@ class IMAGE : public ELEM_HOLDER
{
    friend class SPECCTRA_DB;
    
    std::string     hash;       ///< a hash string used by Compare(), not Format()ed/exported.
    
    std::string     image_id;
    DSN_T           side;
    UNIT_RES*       unit;
@@ -1864,6 +1980,11 @@ public:
        delete place_rules;
    }

    /**
     * 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( IOError )
    {
@@ -1872,34 +1993,40 @@ public:
        out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ),
                                quote, image_id.c_str(), quote );
        
        FormatContents( out, nestLevel+1 );

        out->Print( nestLevel, ")\n" );
    }

    // this is here for makeHash()
    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        if( side != T_both )
            out->Print( 0, " (side %s)", LEXER::GetTokenText( side ) );
        
        out->Print( 0, "\n");
        
        if( unit )
            unit->Format( out, nestLevel+1 );
            unit->Format( out, nestLevel );

        // format the kids, which in this class are the shapes
        ELEM_HOLDER::FormatContents( out, nestLevel+1 );
        ELEM_HOLDER::FormatContents( out, nestLevel );
    
        for( PINS::iterator i=pins.begin();  i!=pins.end();  ++i )
            i->Format( out, nestLevel+1 );
            i->Format( out, nestLevel );

        if( rules )
            rules->Format( out, nestLevel+1 );
            rules->Format( out, nestLevel );
        
        if( place_rules )
            place_rules->Format( out, nestLevel+1 );
            place_rules->Format( out, nestLevel );

        for( KEEPOUTS::iterator i=keepouts.begin();  i!=keepouts.end();  ++i )
            i->Format( out, nestLevel+1 );
        
        out->Print( nestLevel, ")\n" );
            i->Format( out, nestLevel );
    }
    
    
    DSN_T   GetUnits()
    DSN_T   GetUnits() const
    {
        if( unit )
            return unit->GetUnits();
@@ -1907,12 +2034,20 @@ public:
        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;

@@ -1942,6 +2077,13 @@ public:
        delete rules;
    }

    
    /**
     * 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;
@@ -1954,11 +2096,20 @@ public:
        out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ),
                                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( IOError )
    {
        if( unit )
            unit->Format( out, nestLevel+1 );
            unit->Format( out, nestLevel );

        // format the kids, which in this class are the shapes
        ELEM_HOLDER::FormatContents( out, nestLevel+1 );
        ELEM_HOLDER::FormatContents( out, nestLevel );

        out->Print( nestLevel+1, "%s", "" );
        
@@ -1982,12 +2133,11 @@ public:
        out->Print( 0, "\n" );
        
        if( rules )
            rules->Format( out, nestLevel+1 );
        
        out->Print( nestLevel, ")\n" );
            rules->Format( out, nestLevel );
    }

    DSN_T   GetUnits()
    
    DSN_T   GetUnits() const
    {
        if( unit )
            return unit->GetUnits();
@@ -2009,24 +2159,67 @@ class LIBRARY : public ELEM
    friend class SPECCTRA_DB;
    
    UNIT_RES*       unit;
    
    typedef boost::ptr_vector<IMAGE>    IMAGES;
    IMAGES          images;

    PADSTACKS       padstacks;

    /// The start of the vias within the padstacks, which trail the pads.
    /// This field is not Format()ed.
    int             via_start_index;    
    
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 )
    {
        padstacks.push_back( aPadstack );
    }

    void SetViaStartIndex( int aIndex )
    {
        via_start_index = aIndex;
    }
    int GetViaStartIndex()
    {
        return via_start_index;
    }

    int FindIMAGE( IMAGE* aImage )
    {
        for( unsigned i=0;  i<images.size();  ++i )
        {
            if( 0 == IMAGE::Compare( aImage, &images[i] ) )
                return (int) i;
        }
        return -1;
    }
    
    void AppendIMAGE( IMAGE* aImage )
    {
        aImage->SetParent( this );
        images.push_back( aImage );
    }
    
    bool LookupIMAGE( IMAGE* aImage )
    {
        int ndx = FindIMAGE( aImage );
        if( ndx == -1 )
        {
            AppendIMAGE( aImage );
            return false;
        }
        return true;
    }
    
    void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        if( unit )
@@ -2039,18 +2232,13 @@ public:
            i->Format( out, nestLevel );
    }
    
    DSN_T   GetUnits()
    DSN_T   GetUnits() const
    {
        if( unit )
            return unit->GetUnits();
        
        return ELEM::GetUnits();
    }
    
    void AddPadstack( PADSTACK* aPadstack )
    {
        padstacks.push_back( aPadstack );
    }
};


@@ -2422,6 +2610,8 @@ public:

class CONNECT : public ELEM
{
    // @todo not completed.
    
public:
    CONNECT( ELEM* parent ) :
        ELEM( T_connect, parent ) {}
@@ -2695,7 +2885,7 @@ public:
            i->Format( out, nestLevel );
    }

    DSN_T   GetUnits()
    DSN_T   GetUnits() const
    {
        if( unit )
            return unit->GetUnits();
@@ -2780,7 +2970,7 @@ public:
        out->Print( nestLevel, ")\n" ); 
    }
    
    DSN_T   GetUnits()
    DSN_T   GetUnits() const
    {
        if( unit )
            return unit->GetUnits();
@@ -3180,6 +3370,8 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
    
    std::string quote_char;

    STRINGFORMATTER sf;
    
    
    /**
     * Function nextTok
@@ -3321,6 +3513,22 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
    void doSUPPLY_PIN( SUPPLY_PIN* growth ) throw( IOError );    

    
    /**
     * Function makeIMAGE
     * allocates an IMAGE on the heap and creates all the PINs according
     * to the PADs in the MODULE.
     */
    IMAGE* makeIMAGE( MODULE* aModule );

    
    /**
     * Function makePADSTACKs
     * makes all the PADSTACKs, and marks each D_PAD with the index into the 
     * LIBRARY::padstacks list that it matches.
     */
    void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads );
    
    
public:

    SPECCTRA_DB()
@@ -3332,7 +3540,7 @@ public:
        quote_char += '"';
    }

    ~SPECCTRA_DB()
    virtual ~SPECCTRA_DB()
    {
        delete lexer;
        delete pcb;
+94 −59

File changed.

Preview size limit exceeded, changes collapsed.