Commit d7a85428 authored by dickelbeck's avatar dickelbeck
Browse files

more specctra work

parent ed4b9015
Loading
Loading
Loading
Loading
+21 −13
Original line number Original line Diff line number Diff line
@@ -2,7 +2,7 @@
/*
/*
 * This program source code file is part of KICAD, a free EDA CAD application.
 * This program source code file is part of KICAD, a free EDA CAD application.
 *
 *
 * Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com
 * Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 * Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
 * Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
 * 
 * 
 * This program is free software; you can redistribute it and/or
 * This program is free software; you can redistribute it and/or
@@ -506,51 +506,59 @@ int LEXER::findToken( const std::string& tok )
}
}




wxString LEXER::GetTokenText( DSN_T aTok )
const char* LEXER::GetTokenText( DSN_T aTok )
{
{
    wxString    ret;
    const char* ret;
    
    
    if( aTok < 0 )
    if( aTok < 0 )
    {
    {
        switch( aTok )
        switch( aTok )
        {
        {
        case T_QUOTE_DEF:
        case T_QUOTE_DEF:
            ret << _("'quoted text delimiter'");
            ret = "'quoted text delimiter'";
            break;
            break;
        case T_DASH:
        case T_DASH:
            ret << wxT( "'-'" );
            ret = "'-'";
            break;
            break;
        case T_SYMBOL:
        case T_SYMBOL:
            ret << _("'symbol'");
            ret = "'symbol'";
            break;
            break;
        case T_NUMBER:
        case T_NUMBER:
            ret << _("'number'");
            ret = "'number'";
            break;
            break;
        case T_RIGHT:
        case T_RIGHT:
            ret << wxT( "')'" );
            ret = "')'";
            break;
            break;
        case T_LEFT:
        case T_LEFT:
            ret << wxT( "'('" );
            ret = "'('";
            break;
            break;
        case T_STRING:
        case T_STRING:
            ret << _("\"quoted string\"");
            ret = "'quoted string'";
            break;
            break;
        case T_EOF:
        case T_EOF:
            ret << _("'end of file'");
            ret = "'end of file'";
            break;
            break;
        default:
        default:
            ;
            ret = "???";
        }
        }
    }
    }
    else
    else
    {
    {
        ret << wxT("'") << CONV_FROM_UTF8( tokens[aTok].name ) << wxT("'");
        ret = tokens[aTok].name;
    }
    }
    
    
    return ret;
    return ret;
}
}




wxString LEXER::GetTokenString( DSN_T aTok )
{
    wxString    ret = CONV_FROM_UTF8( GetTokenText(aTok) );

    return ret;    
}

    
void LEXER::ThrowIOError( wxString aText, int charOffset ) throw (IOError)
void LEXER::ThrowIOError( wxString aText, int charOffset ) throw (IOError)
{
{
    aText << wxT(" ") << _("in file") << wxT(" \"") << filename 
    aText << wxT(" ") << _("in file") << wxT(" \"") << filename 
+12 −2
Original line number Original line Diff line number Diff line
/*
/*
 * This program source code file is part of KICAD, a free EDA CAD application.
 * This program source code file is part of KICAD, a free EDA CAD application.
 *
 *
 * Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com
 * Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 * Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
 * Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
 * 
 * 
 * This program is free software; you can redistribute it and/or
 * This program is free software; you can redistribute it and/or
@@ -607,7 +607,17 @@ public:
    void ThrowIOError( wxString aText, int charOffset ) throw (IOError);
    void ThrowIOError( wxString aText, int charOffset ) throw (IOError);




    wxString GetTokenText( DSN_T aTok );
    /**
     * Function GetTokenString
     * returns the wxString representation of a DSN_T value.
     */
    static wxString GetTokenString( DSN_T aTok );
    
    /**
     * Function GetTokenString
     * returns the C string representation of a DSN_T value.
     */
    static const char* GetTokenText( DSN_T aTok );


    
    
    /**
    /**
+415 −106
Original line number Original line Diff line number Diff line
@@ -2,7 +2,7 @@
/*
/*
 * This program source code file is part of KICAD, a free EDA CAD application.
 * This program source code file is part of KICAD, a free EDA CAD application.
 *
 *
 * Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com
 * Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 * Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
 * Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
 * 
 * 
 * This program is free software; you can redistribute it and/or
 * This program is free software; you can redistribute it and/or
@@ -32,12 +32,23 @@
#include <wx/ffile.h>
#include <wx/ffile.h>
#include "fctsys.h"
#include "fctsys.h"
#include "pcbstruct.h"
#include "pcbstruct.h"

#include "dsn.h"
#include "dsn.h"




#define EDA_BASE            // build_version.h behavior
#undef  COMMON_GLOBL
#define COMMON_GLOBL        // build_version.h behavior
#include "build_version.h"


namespace DSN {
namespace DSN {


    
    
class SPECCTRA_DB;
class PCB;


/**
/**
 * Class ELEM
 * Class ELEM
 * is a base class for any DSN element.  It is not a parent node so it 
 * is a base class for any DSN element.  It is not a parent node so it 
@@ -64,6 +75,28 @@ public:
 */ 
 */ 




/**
 * Class OUTPUTFORMATTER
 * is an interface (abstract class) used to output ASCII text.
 */
class OUTPUTFORMATTER
{
public:

    /**
     * Function print
     * formats and writes text to the output stream.
     *
     * @param nestLevel The multiple of spaces to preceed the output with. 
     * @param fmt A printf style format string.
     * @param ... a variable list of parameters that will get blended into 
     *  the output under control of the format string.
     * @throw IOError if there is a problem outputting, such as a full disk.
     */
    virtual void Print( int nestLevel, const char* fmt, ... ) throw( IOError ) = 0;
};
 
 


/**
/**
 * Class ELEM
 * Class ELEM
@@ -75,25 +108,46 @@ class ELEM
protected:    
protected:    
    DSN_T           type;
    DSN_T           type;


    ELEM*           parent;
    
    //  see http://www.boost.org/libs/ptr_container/doc/ptr_sequence_adapter.html
    //  see http://www.boost.org/libs/ptr_container/doc/ptr_sequence_adapter.html
    typedef boost::ptr_vector<ELEM> ELEM_ARRAY;
    typedef boost::ptr_vector<ELEM> ELEM_ARRAY;
    
    
    ELEM_ARRAY                      kids;      ///< of pointers                   
    ELEM_ARRAY      kids;      ///< ELEM pointers                   
   


public:
public:


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

    
    /**
     * Function GetUnits
     * returns the units for this section.  Derived classes may override this
     * to check for section specific overrides.
     * @return DSN_T - one of the allowed values to <unit_descriptor>
     */
    virtual DSN_T   GetUnits()
    {
    {
        // printf("~ELEM(%p %d)\n", this, Type() );
        if( parent )
            return parent->GetUnits();
        
        return T_inch;
    }
    }


    DSN_T   Type() { return type; }
    
    /**
     * Function Save
     * writes this object out in ASCII form 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 IOError if a system error writing the output, such as a full disk.
     */
    virtual void Save( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError );

    
    
    //-----< list operations >--------------------------------------------
    //-----< list operations >--------------------------------------------


@@ -104,25 +158,12 @@ public:
     * @param instanceNum The instance number of to find: 0 for first, 1 for second, etc.
     * @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.
     * @return int - The index into the kids array or -1 if not found.
     */
     */
    int FindElem( DSN_T aType, int instanceNum )
    int FindElem( DSN_T aType, int instanceNum = 0 );
    {
        int repeats=0;
        for( unsigned i=0;  i<kids.size();  ++i )
        {
            if( kids[i].Type() == aType )
            {
                if( repeats == instanceNum )
                    return i;
                ++repeats;
            }
        }
        return -1;
    }


    
    
    /**
    /**
     * Function Length
     * Function Length
     * returns the number ELEMs in this ELEM.
     * returns the number of ELEMs in this ELEM.
     * @return int - the count of children
     * @return int - the count of children
     */
     */
    int     Length() const
    int     Length() const
@@ -147,58 +188,254 @@ public:
        return ret.release();
        return ret.release();
    }
    }


/*    
    void    Insert( int aIndex, ELEM* aElem )
    ELEM& operator[]( int aIndex )
    {
    {
        return kids[aIndex];
        kids.insert( kids.begin()+aIndex, aElem );
    }
    }
    
    
    const ELEM& operator[]( int aIndex ) const
    ELEM*   At( int aIndex )
    {
    {
        return kids[aIndex];
        // we have varying sized objects and are using polymorphism, so we
        // must return a pointer not a reference.
        return &kids[aIndex];
    }
    }
    
    ELEM* operator[]( int aIndex )
    {
        return At( aIndex );
    }
    
    void    Delete( int aIndex )
    {
        kids.erase( kids.begin()+aIndex );
    }
};



ELEM::ELEM( DSN_T aType, ELEM* aParent ) :
   type( aType ),
   parent( aParent )
{
}


ELEM::~ELEM()
{
}


void ELEM::Save( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
    out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) ); 
    
    for( int i=0;  i<Length();  ++i )
    {
        At(i)->Save( out, nestLevel+1 );
    }
    
    out->Print( nestLevel, ")\n" ); 
}


int ELEM::FindElem( DSN_T aType, int instanceNum )
{
    int repeats=0;
    for( unsigned i=0;  i<kids.size();  ++i )
    {
        if( kids[i].Type() == aType )
        {
            if( repeats == instanceNum )
                return i;
            ++repeats;
        }
    }
    return -1;
}


/**
 * Class PARSER
 * is simply a configuration record per the SPECCTRA DSN file spec.
 * It is not actually a parser.
 */
 */
class PARSER : public ELEM
{
    friend class SPECCTRA_DB;


    void    Insert( int aIndex, ELEM* aElem )
    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;
    
    std::string const_id1;
    std::string const_id2;
    
    std::string host_cad;
    std::string host_version;

    
public:

    PARSER( ELEM* aParent ) :
        ELEM( T_parser, aParent )
    {
    {
        kids.insert( kids.begin()+aIndex, aElem );
        string_quote = '"';
        space_in_quoted_tokens = false;

        case_sensitive = false;
        wires_include_testpoint = false;
        routes_include_testpoint = false;
        routes_include_guides = false;
        routes_include_image_conductor = false;
        via_rotate_first = true;
        
        host_cad = "Kicad's PCBNEW";
        host_version = CONV_TO_UTF8(g_BuildVersion);
    }
    }


    ELEM* operator[]( int aIndex )
    void Save( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
    {
        // we have varying sized object and are using polymorphism, so we
        out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) ); 
        // must return a pointer not a reference.
        out->Print( nestLevel+1, "(string_quote %c)\n", string_quote );
        return &kids[aIndex];
        out->Print( nestLevel+1, "(space_in_quoted_tokens %s)\n", space_in_quoted_tokens ? "on" : "off" );
        out->Print( nestLevel+1, "(host_cad \"%s\")\n", host_cad.c_str() ); 
        out->Print( nestLevel+1, "(host_version \"%s\")\n", host_version.c_str() );
        out->Print( nestLevel+1, "(case_sensitive %s)\n", case_sensitive ? "on" : "off" );
        out->Print( nestLevel, ")\n" ); 
    }
    }
    
    
    void    Delete( int aIndex )
};


class RESOLUTION : public ELEM
{
{
        kids.erase( kids.begin()+aIndex );
    friend class SPECCTRA_DB;
    
    DSN_T       units;
    int         value;

public:
    RESOLUTION( ELEM* aParent ) :
        ELEM( T_resolution, aParent )
    {
        units = T_inch;
        value = 2540000;
    }

    void Save( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        out->Print( nestLevel, "(%s %s %d)\n", LEXER::GetTokenText( Type() ), 
                   LEXER::GetTokenText(units), value ); 
    }
    
    DSN_T   GetUnits()
    {
        return units;
    }
};


class UNIT : public ELEM
{
    friend class SPECCTRA_DB;
    
    DSN_T       units;

public:
    UNIT( ELEM* aParent ) :
        ELEM( T_unit, aParent )
    {
        units = T_inch;
    }
        
    void Save( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        out->Print( nestLevel, "(%s %s)\n", LEXER::GetTokenText( Type() ), 
                   LEXER::GetTokenText(units) ); 
    }
    
    DSN_T   GetUnits()
    {
        return units;
    }
    }
};
};




class PCB : public ELEM
{
    friend class SPECCTRA_DB;
    
    PARSER*         parser;
    RESOLUTION*     resolution;
    UNIT*           unit;
    
public:
    
    PCB() :
        ELEM( T_pcb )
    {
        parser = 0;
        resolution = 0;
        unit = 0;
    }
    
    ~PCB()
    {
        delete parser;
        delete resolution;
        delete unit;
    }
    
    void Save( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) );
        
        if( parser )
            parser->Save( out, nestLevel+1 );
        
        if( resolution )
            resolution->Save( out, nestLevel+1 );

        if( unit )
            unit->Save( out, nestLevel+1 );
        
        out->Print( nestLevel, ")\n" ); 
    }
    
    DSN_T   GetUnits()
    {
        if( unit )
            return unit->GetUnits();
        
        if( resolution )
            return resolution->GetUnits();
        
        return ELEM::GetUnits();
    }
    
};



/**
/**
 * Class SPECCTRA_DB
 * Class SPECCTRA_DB
 * holds a DSN data tree, usually coming from a DSN file.
 * holds a DSN data tree, usually coming from a DSN file.
 */
 */
class SPECCTRA_DB
class SPECCTRA_DB : public OUTPUTFORMATTER
{
{
    LEXER*      lexer;
    LEXER*      lexer;
    
    
    ELEM*   tree;    
    PCB*        tree;    


    FILE*       fp;
    FILE*       fp;


    wxString    filename;
    
    
    /**
     * Function print
     * formats and writes text to the output stream.
     * @param fmt A printf style format string.
     * @param ... a variable list of parameters that will get blended into 
     *  the output under control of the format string.
     */
    void print( const char* fmt, ... );
    
    
    /**
    /**
     * Function nextTok
     * Function nextTok
@@ -209,10 +446,10 @@ class SPECCTRA_DB
    void    expecting( DSN_T ) throw( IOError );
    void    expecting( DSN_T ) throw( IOError );
    void    expecting( const wxChar* text ) throw( IOError );
    void    expecting( const wxChar* text ) throw( IOError );
    
    
    void doPCB( ELEM* growth ) throw(IOError);
    void doPCB( PCB* growth ) throw(IOError);
    void doPARSER( ELEM* growth ) throw(IOError);
    void doPARSER( PARSER* growth ) throw(IOError);
    void doRESOLUTION( ELEM* growth ) throw(IOError);
    void doRESOLUTION( RESOLUTION* growth ) throw(IOError);
    
    void doUNIT( UNIT* growth ) throw( IOError );    
    
    
public:
public:


@@ -233,6 +470,28 @@ public:
    }
    }


    
    
    //-----<OUTPUTFORMATTER>-------------------------------------------------
    void Print( int nestLevel, const char* fmt, ... ) throw( IOError );
    //-----</OUTPUTFORMATTER>------------------------------------------------

    /**
     * Function MakePCB
     * makes 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( const PCB* aPcb )
    {
        delete tree;
        tree = (PCB*) aPcb;
    }

    
    /**
    /**
     * Function Load
     * Function Load
     * is a recursive descent parser for a DSN file.
     * is a recursive descent parser for a DSN file.
@@ -249,7 +508,7 @@ public:
     * writes the given BOARD out as a SPECTRA DSN format file.
     * writes the given BOARD out as a SPECTRA DSN format file.
     * @param aBoard The BOARD to save.
     * @param aBoard The BOARD to save.
     */
     */
    void Export( BOARD* aBoard );
    void Export( wxString, BOARD* aBoard );
};
};




@@ -270,7 +529,7 @@ void SPECCTRA_DB::expecting( DSN_T aTok ) throw( IOError )
{
{
    wxString    errText( _("Expecting") );
    wxString    errText( _("Expecting") );
    
    
    errText << wxT(" ") << lexer->GetTokenText( aTok );
    errText << wxT(" ") << LEXER::GetTokenString( aTok );
    
    
    lexer->ThrowIOError( errText, lexer->CurOffset() ); 
    lexer->ThrowIOError( errText, lexer->CurOffset() ); 
}
}
@@ -293,13 +552,17 @@ DSN_T SPECCTRA_DB::nextTok()


void SPECCTRA_DB::Load( const wxString& filename ) throw( IOError )
void SPECCTRA_DB::Load( const wxString& filename ) throw( IOError )
{
{
    wxFFile     file( filename.c_str() );
    wxFFile     file;
    
    FILE*       fp = wxFopen( filename, wxT("r") );
    
    
    if( !file.IsOpened() )
    if( !fp )
    {
    {
        ThrowIOError( _("Unable to open file \"%s\""), filename.GetData() );  
        ThrowIOError( _("Unable to open file \"%s\""), filename.GetData() );  
    }
    }


    file.Attach( fp );      // "exception safe" way to close the file.
    
    delete lexer;  
    delete lexer;  
    lexer = 0;
    lexer = 0;
    
    
@@ -311,29 +574,18 @@ void SPECCTRA_DB::Load( const wxString& filename ) throw( IOError )
    if( nextTok() != T_pcb )
    if( nextTok() != T_pcb )
        expecting( T_pcb );
        expecting( T_pcb );


    delete tree;
    SetPCB( new PCB() );
    tree = 0;
    
    tree = new ELEM( T_pcb );
    
    
    doPCB( tree );
    doPCB( tree );
}
}




void SPECCTRA_DB::doPCB( ELEM* growth ) throw( IOError )
void SPECCTRA_DB::doPCB( PCB* growth ) throw( IOError )
{
{
    ELEM* child;
    DSN_T tok = nextTok();
    DSN_T tok = nextTok();
    
    
    switch( tok )
    if( tok!=T_SYMBOL && tok!=T_STRING )
    {
        expecting( T_SYMBOL );
    case T_SYMBOL:
    case T_STRING:
        break;
        
    default:
        expecting( T_STRING );
    }
    
    
    while( (tok = nextTok()) != T_RIGHT )
    while( (tok = nextTok()) != T_RIGHT )
    {
    {
@@ -344,20 +596,18 @@ void SPECCTRA_DB::doPCB( ELEM* growth ) throw( IOError )
        switch( tok )
        switch( tok )
        {
        {
        case T_parser:
        case T_parser:
            child = new ELEM( T_parser );
            growth->parser = new PARSER( growth );
            growth->Append( child );
            doPARSER( growth->parser );
            doPARSER( child );
            break;
            break;
            
            
        case T_unit:
        case T_unit:
            child = new ELEM( T_unit );
            growth->unit = new UNIT( growth );
            growth->Append( child );
            doUNIT( growth->unit );
            break;
            break;
            
            
        case T_resolution:
        case T_resolution:
            child = new ELEM( T_resolution );
            growth->resolution = new RESOLUTION( growth );
            growth->Append( child );
            doRESOLUTION( growth->resolution );
            doRESOLUTION( child );
            break;
            break;
            
            
        case T_structure:
        case T_structure:
@@ -376,7 +626,7 @@ void SPECCTRA_DB::doPCB( ELEM* growth ) throw( IOError )
}
}




void SPECCTRA_DB::doPARSER( ELEM* growth ) throw( IOError )
void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
{
{
    DSN_T   tok;
    DSN_T   tok;
    
    
@@ -398,22 +648,23 @@ void SPECCTRA_DB::doPARSER( ELEM* growth ) throw( IOError )
        case T_space_in_quoted_tokens:
        case T_space_in_quoted_tokens:
            tok = nextTok();
            tok = nextTok();
            if( tok!=T_on && tok!=T_off )
            if( tok!=T_on && tok!=T_off )
                expecting( _("on or off") );
                expecting( wxT("on|off") );
            lexer->SetSpaceInQuotedTokens( tok==T_on );
            lexer->SetSpaceInQuotedTokens( tok==T_on );
            growth->space_in_quoted_tokens = (tok==T_on);
            break;
            break;
            
            
        case T_host_cad:
        case T_host_cad:
            tok = nextTok();
            tok = nextTok();
            if( tok!=T_STRING && tok!=T_SYMBOL )
            if( tok!=T_STRING && tok!=T_SYMBOL )
                expecting( T_SYMBOL );
                expecting( T_SYMBOL );
            // @todo
            growth->host_cad = lexer->CurText();
            break;
            break;
            
            
        case T_host_version:
        case T_host_version:
            tok = nextTok();
            tok = nextTok();
            if( tok!=T_STRING && tok!=T_SYMBOL )
            if( tok!=T_STRING && tok!=T_SYMBOL )
                expecting( T_SYMBOL );
                expecting( T_SYMBOL );
            // @todo
            growth->host_version = lexer->CurText();
            break;
            break;


        case T_constant:
        case T_constant:
@@ -464,14 +715,14 @@ void SPECCTRA_DB::doPARSER( ELEM* growth ) throw( IOError )
        case T_case_sensitive:
        case T_case_sensitive:
            tok = nextTok();
            tok = nextTok();
            if( tok!=T_on && tok!=T_off )
            if( tok!=T_on && tok!=T_off )
                expecting( _("on or off") );
                expecting( wxT("on|off") );
            // @todo
            growth->case_sensitive = (tok==T_on);
            break;
            break;


        case T_via_rotate_first:    // [(via_rotate_first [on | off])]
        case T_via_rotate_first:    // [(via_rotate_first [on | off])]
            tok = nextTok();
            tok = nextTok();
            if( tok!=T_on && tok!=T_off )
            if( tok!=T_on && tok!=T_off )
                expecting( _("on or off") );
                expecting( wxT("on|off") );
            // @todo
            // @todo
            break;
            break;
            
            
@@ -484,10 +735,9 @@ void SPECCTRA_DB::doPARSER( ELEM* growth ) throw( IOError )
        if( tok != T_RIGHT )
        if( tok != T_RIGHT )
            expecting( T_RIGHT );
            expecting( T_RIGHT );
    }
    }
    
}
}


void SPECCTRA_DB::doRESOLUTION( ELEM* growth ) throw(IOError)
void SPECCTRA_DB::doRESOLUTION( RESOLUTION* growth ) throw(IOError)
{
{
    DSN_T   tok = nextTok();
    DSN_T   tok = nextTok();


@@ -498,35 +748,88 @@ void SPECCTRA_DB::doRESOLUTION( ELEM* growth ) throw(IOError)
    case T_cm:
    case T_cm:
    case T_mm:
    case T_mm:
    case T_um:
    case T_um:
        // @todo
        growth->units = tok;
        break;
        break;
    default:
    default:
        expecting( wxT("inch, mil, cm, mm, or um") );
        expecting( wxT("inch | mil | cm | mm | um") );
    }
    }
    
    
    tok = nextTok();
    tok = nextTok();
    if( tok != T_NUMBER )
    if( tok != T_NUMBER )
        expecting( T_NUMBER );
        expecting( T_NUMBER );


    growth->value = atoi( lexer->CurText() );
    
    tok = nextTok();
    tok = nextTok();
    if( tok != T_RIGHT )
    if( tok != T_RIGHT )
        expecting( T_RIGHT );
        expecting( T_RIGHT );
}
}


void SPECCTRA_DB::doUNIT( UNIT* growth ) throw(IOError)
{
    DSN_T   tok = nextTok();


void SPECCTRA_DB::print( const char* fmt, ... )
    switch( tok )
    {
    case T_inch:
    case T_mil:
    case T_cm:
    case T_mm:
    case T_um:
        growth->units = tok;
        break;
    default:
        expecting( wxT("inch | mil | cm | mm | um") );
    }
    
    tok = nextTok();
    if( tok != T_RIGHT )
        expecting( T_RIGHT );
}


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


    va_start( args, fmt );
    va_start( args, fmt );
    vfprintf( fp, fmt, args );
    
    int ret = 0;
    
    for( int i=0; i<nestLevel;  ++i )
    {
        ret = fprintf( fp, "  " );
        if( ret < 0 )
            break;
    }
    
    if( ret<0 || vfprintf( fp, fmt, args )<0 )
        ThrowIOError( _("System file error writing to file \"%s\""), filename.GetData() );
    
    va_end( args );
    va_end( args );
}
}




void SPECCTRA_DB::Export( wxString filename, BOARD* aBoard )
{
    fp = wxFopen( filename, wxT("w") );
    
    
void SPECCTRA_DB::Export( BOARD* aBoard )
    if( !fp )
    {
    {
        ThrowIOError( _("Unable to open file \"%s\""), filename.GetData() );  
    }

    tree->Save( this, 0 );    
}


PCB* SPECCTRA_DB::MakePCB()
{
    PCB*    pcb = new PCB();
    
    pcb->parser = new PARSER( pcb );

    return pcb;
}
}




@@ -555,6 +858,7 @@ int main( int argc, char** argv )
//    wxString    filename( wxT("/tmp/testdesigns/test.dsn") );
//    wxString    filename( wxT("/tmp/testdesigns/test.dsn") );


    SPECCTRA_DB     db;
    SPECCTRA_DB     db;
    bool            failed = false;
    
    
    try 
    try 
    {
    {
@@ -563,11 +867,16 @@ int main( int argc, char** argv )
    catch( IOError ioe )
    catch( IOError ioe )
    {
    {
        printf( "%s\n", CONV_TO_UTF8(ioe.errorText) );
        printf( "%s\n", CONV_TO_UTF8(ioe.errorText) );
        exit(1);
        failed = true;
    }
    }


    if( !failed )    
        printf("loaded OK\n");
        printf("loaded OK\n");


//    db.SetPCB( SPECCTRA_DB::MakePCB() );
    
    db.Export( wxT("/tmp/export.dsn"), 0 );
    
#endif
#endif
    
    
}
}