From 063907211e3653e1d71179cda9de02f88fd0e076 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Sat, 8 Dec 2012 17:58:03 -0600 Subject: [PATCH] more fp_lib_table work, enhance parser --- common/dsnlexer.cpp | 10 ++- common/fp_lib_table.cpp | 136 +++++++++++++++++++++++++---------- common/fp_lib_table.keywords | 8 +-- common/richio.cpp | 51 ++++++++++--- include/fp_lib_table.h | 124 ++++++++++++++++---------------- include/richio.h | 20 +----- pcbnew/pcb_plot_params.h | 7 +- pcbnew/pcbnew_config.cpp | 38 ++++++++++ 8 files changed, 251 insertions(+), 143 deletions(-) diff --git a/common/dsnlexer.cpp b/common/dsnlexer.cpp index f49d9ec0c7..b2eb6880c9 100644 --- a/common/dsnlexer.cpp +++ b/common/dsnlexer.cpp @@ -304,9 +304,8 @@ void DSNLEXER::Unexpected( int aTok ) throw( IO_ERROR ) void DSNLEXER::Duplicate( int aTok ) throw( IO_ERROR ) { - wxString errText; - - errText.Printf( _("%s is a duplicate"), GetTokenString( aTok ).GetData() ); + wxString errText = wxString::Format( + _("%s is a duplicate"), GetTokenString( aTok ).GetData() ); THROW_PARSE_ERROR( errText, CurSource(), CurLine(), CurLineNumber(), CurOffset() ); } @@ -358,9 +357,8 @@ int DSNLEXER::NeedNUMBER( const char* aExpectation ) throw( IO_ERROR ) int tok = NextTok(); if( tok != DSN_NUMBER ) { - wxString errText; - - errText.Printf( _("need a NUMBER for '%s'"), wxString::FromUTF8( aExpectation ).GetData() ); + wxString errText = wxString::Format( + _("need a NUMBER for '%s'"), wxString::FromUTF8( aExpectation ).GetData() ); THROW_PARSE_ERROR( errText, CurSource(), CurLine(), CurLineNumber(), CurOffset() ); } return tok; diff --git a/common/fp_lib_table.cpp b/common/fp_lib_table.cpp index 3cb01343b0..301d0db680 100644 --- a/common/fp_lib_table.cpp +++ b/common/fp_lib_table.cpp @@ -24,6 +24,8 @@ */ +#include // wxExpandEnvVars() + #include #include @@ -45,11 +47,29 @@ FP_LIB_TABLE::FP_LIB_TABLE( FP_LIB_TABLE* aFallBackTable ) : void FP_LIB_TABLE::Parse( FP_LIB_TABLE_LEXER* in ) throw( IO_ERROR, PARSE_ERROR ) { - T tok; + /* + (fp_lib_table + (lib (name NICKNAME)(descr DESCRIPTION)(type TYPE)(full_uri FULL_URI)(options OPTIONS)) + : + ) + + Elements after (name) are order independent. + */ + + T tok; + + // This table may be nested within a larger s-expression, or not. + // Allow for parser of that optional outter s-epression to have looked ahead. + if( in->CurTok() != T_fp_lib_table ) + { + in->NeedLEFT(); + if( ( tok = in->NextTok() ) != T_fp_lib_table ) + in->Expecting( T_fp_lib_table ); + } while( ( tok = in->NextTok() ) != T_RIGHT ) { - // (lib (name "LOGICAL")(type "TYPE")(full_uri "FULL_URI")(options "OPTIONS")) + ROW row; // reconstructed for each row in input stream. if( tok == T_EOF ) in->Expecting( T_RIGHT ); @@ -57,10 +77,14 @@ void FP_LIB_TABLE::Parse( FP_LIB_TABLE_LEXER* in ) throw( IO_ERROR, PARSE_ERROR if( tok != T_LEFT ) in->Expecting( T_LEFT ); - if( ( tok = in->NextTok() ) != T_fp_lib ) - in->Expecting( T_fp_lib ); + // in case there is a "row integrity" error, tell where later. + int lineNum = in->CurLineNumber(); + int offset = in->CurOffset(); - // (name "LOGICAL_NAME") + if( ( tok = in->NextTok() ) != T_lib ) + in->Expecting( T_lib ); + + // (name LOGICAL_NAME) in->NeedLEFT(); if( ( tok = in->NextTok() ) != T_name ) @@ -68,48 +92,74 @@ void FP_LIB_TABLE::Parse( FP_LIB_TABLE_LEXER* in ) throw( IO_ERROR, PARSE_ERROR in->NeedSYMBOLorNUMBER(); - ROW row; - row.SetNickName( in->FromUTF8() ); in->NeedRIGHT(); - // (uri "FULL_URI") - in->NeedLEFT(); + // After (name), remaining (lib) elements are order independent, and in + // the future, perhaps optional. Flexibility for future changes. - if( ( tok = in->NextTok() ) != T_full_uri ) - in->Expecting( T_full_uri ); + bool sawType = false; + bool sawOpts = false; + bool sawDesc = false; + bool sawUri = false; - in->NeedSYMBOLorNUMBER(); + while( ( tok = in->NextTok() ) != T_RIGHT ) + { + if( tok == T_EOF ) + in->Unexpected( T_EOF ); - row.SetFullURI( in->FromUTF8() ); + if( tok != T_LEFT ) + in->Expecting( T_LEFT ); - in->NeedRIGHT(); + tok = in->NeedSYMBOLorNUMBER(); - // (type "TYPE") - in->NeedLEFT(); + switch( tok ) + { + case T_uri: + if( sawUri ) + in->Duplicate( tok ); + sawUri = true; + in->NeedSYMBOLorNUMBER(); + row.SetFullURI( in->FromUTF8() ); + break; - if( ( tok = in->NextTok() ) != T_type ) + case T_type: + if( sawType ) + in->Duplicate( tok ); + sawType = true; + in->NeedSYMBOLorNUMBER(); + row.SetType( in->FromUTF8() ); + break; + + case T_options: + if( sawOpts ) + in->Duplicate( tok ); + sawOpts = true; + in->NeedSYMBOLorNUMBER(); + row.SetOptions( in->FromUTF8() ); + break; + + case T_descr: + if( sawDesc ) + in->Duplicate( tok ); + sawDesc = true; + in->NeedSYMBOLorNUMBER(); + row.SetDescr( in->FromUTF8() ); + break; + + default: + in->Unexpected( tok ); + } + + in->NeedRIGHT(); + } + + if( !sawType ) in->Expecting( T_type ); - in->NeedSYMBOLorNUMBER(); - - row.SetType( in->FromUTF8() ); - - in->NeedRIGHT(); - - // (options "OPTIONS") - in->NeedLEFT(); - - if( ( tok = in->NextTok() ) != T_options ) - in->Expecting( T_options ); - - in->NeedSYMBOLorNUMBER(); - - row.SetOptions( in->FromUTF8() ); - - in->NeedRIGHT(); - in->NeedRIGHT(); // terminate the (lib..) + if( !sawUri ) + in->Expecting( T_uri ); // all nickNames within this table fragment must be unique, so we do not // use doReplace in InsertRow(). (However a fallBack table can have a @@ -119,9 +169,8 @@ void FP_LIB_TABLE::Parse( FP_LIB_TABLE_LEXER* in ) throw( IO_ERROR, PARSE_ERROR { wxString msg = wxString::Format( _( "'%s' is a duplicate footprint library nickName" ), - GetChars( row.nickName ) - ); - THROW_IO_ERROR( msg ); + GetChars( row.nickName ) ); + THROW_PARSE_ERROR( msg, in->CurSource(), in->CurLine(), lineNum, offset ); } } } @@ -142,8 +191,9 @@ void FP_LIB_TABLE::Format( OUTPUTFORMATTER* out, int nestLevel ) const void FP_LIB_TABLE::ROW::Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR ) { - out->Print( nestLevel, "(lib (name %s)(full_uri %s)(type %s)(options %s))\n", + out->Print( nestLevel, "(lib (name %s)(descr %s)(uri %s)(type %s)(options %s))\n", out->Quotew( GetNickName() ).c_str(), + out->Quotew( GetDescr() ).c_str(), out->Quotew( GetFullURI() ).c_str(), out->Quotew( GetType() ).c_str(), out->Quotew( GetOptions() ).c_str() @@ -252,6 +302,14 @@ PLUGIN* FP_LIB_TABLE::PluginFind( const wxString& aLibraryNickName ) } +const wxString FP_LIB_TABLE::ExpandSubtitutions( const wxString aString ) +{ + // We reserve the right to do this another way, but providing our own member + // function. + return wxExpandEnvVars( aString ); +} + + #if 0 // don't know that this is needed yet MODULE* FP_LIB_TABLE::LookupFootprint( const FP_LIB_ID& aFootprintId ) throw( IO_ERROR ) diff --git a/common/fp_lib_table.keywords b/common/fp_lib_table.keywords index 6a678ed707..27b1242e2c 100644 --- a/common/fp_lib_table.keywords +++ b/common/fp_lib_table.keywords @@ -1,9 +1,7 @@ fp_lib_table +lib name type -kicad -legacy -eagle -full_uri +uri options -fp_lib +descr diff --git a/common/richio.cpp b/common/richio.cpp index 19ccb838f7..698c19baed 100644 --- a/common/richio.cpp +++ b/common/richio.cpp @@ -39,27 +39,58 @@ // "richio" after its author, Richard Hollenbeck, aka Dick Hollenbeck. + +void IO_ERROR::init( const char* aThrowersFile, const char* aThrowersLoc, const wxString& aMsg ) +{ + errorText.Printf( IO_FORMAT, aMsg.GetData(), + wxString::FromUTF8( aThrowersFile ).GetData(), + wxString::FromUTF8( aThrowersLoc ).GetData() ); +} + + +void PARSE_ERROR::init( const char* aThrowersFile, const char* aThrowersLoc, + const wxString& aMsg, const wxString& aSource, + const char* aInputLine, + int aLineNumber, int aByteIndex ) +{ + // save inpuLine, lineNumber, and offset for UI (.e.g. Sweet text editor) + inputLine = aInputLine; + lineNumber = aLineNumber; + byteIndex = aByteIndex; + + errorText.Printf( PARSE_FORMAT, aMsg.GetData(), aSource.GetData(), + aLineNumber, aByteIndex, + wxString::FromUTF8( aThrowersFile ).GetData(), + wxString::FromUTF8( aThrowersLoc ).GetData() ); +} + + //----------------------------------------------------------- LINE_READER::LINE_READER( unsigned aMaxLineLength ) { lineNum = 0; - if( aMaxLineLength == 0 ) // caller is goofed up. - aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX; + if( aMaxLineLength == 0 ) + { + line = 0; + } + else + { + maxLineLength = aMaxLineLength; - maxLineLength = aMaxLineLength; + // start at the INITIAL size, expand as needed up to the MAX size in maxLineLength + capacity = LINE_READER_LINE_INITIAL_SIZE; - // start at the INITIAL size, expand as needed up to the MAX size in maxLineLength - capacity = LINE_READER_LINE_INITIAL_SIZE; + // but never go above user's aMaxLineLength, and leave space for trailing nul + if( capacity > aMaxLineLength+1 ) + capacity = aMaxLineLength+1; - // but never go above user's aMaxLineLength, and leave space for trailing nul - if( capacity > aMaxLineLength+1 ) - capacity = aMaxLineLength+1; + line = new char[capacity]; - line = new char[capacity]; + line[0] = '\0'; + } - line[0] = '\0'; length = 0; } diff --git a/include/fp_lib_table.h b/include/fp_lib_table.h index 2d23bee00e..b5281d1541 100644 --- a/include/fp_lib_table.h +++ b/include/fp_lib_table.h @@ -41,7 +41,7 @@ class FP_LIB_TABLE_LEXER; /** * Class FP_LIB_TABLE - * holds FP_LIB_TABLE::ROW records, and can be searched based on logical library name. + * holds FP_LIB_TABLE::ROW records (rows), and can be searched based on library nickName. *

* This class owns the footprint library table, which is like fstab in concept and maps * logical library name to the library URI, type, and options. It is heavily based on the SWEET @@ -104,10 +104,12 @@ public: { } - ROW( const wxString& aNick, const wxString& aURI, const wxString& aType, const wxString& aOptions ) : + ROW( const wxString& aNick, const wxString& aURI, const wxString& aType, + const wxString& aOptions, const wxString& aDescr = wxEmptyString ) : nickName( aNick ), uri( aURI ), - options( aOptions ) + options( aOptions ), + description( aDescr ) { SetType( aType ); } @@ -119,42 +121,69 @@ public: bool operator!=( const ROW& r ) const { return !( *this == r ); } + //----------------------------------------------------------- + /** * Function GetNickName * returns the short name of this library table row. */ - const wxString& GetNickName() const - { - return nickName; - } + const wxString& GetNickName() const { return nickName; } + + /** + * Function SetNickName + * changes the logical name of this library, useful for an editor. + */ + void SetNickName( const wxString& aNickName ) { nickName = aNickName; } /** * Function GetType - * returns the type of LIB represented by this record. + * returns the type of LIB represented by this row. */ - const wxString GetType() const - { - return IO_MGR::ShowType( type ); - } + const wxString GetType() const { return IO_MGR::ShowType( type ); } + + /** + * Function SetType + * changes the type represented by this row. + */ + void SetType( const wxString& aType ) { type = IO_MGR::EnumFromStr( aType ); } /** * Function GetFullURI * returns the full location specifying URI for the LIB. */ - const wxString& GetFullURI() const - { - return uri; - } + const wxString& GetFullURI() const { return uri; } + + /** + * Function SetFullURI + * changes the full URI for the library. + */ + void SetFullURI( const wxString& aFullURI ) { uri = aFullURI; } /** * Function GetOptions * returns the options string, which may hold a password or anything else needed to * instantiate the underlying LIB_SOURCE. */ - const wxString& GetOptions() const - { - return options; - } + const wxString& GetOptions() const { return options; } + + /** + * Function SetOptions + */ + void SetOptions( const wxString& aOptions ) { options = aOptions; } + + /** + * Function GetDescr + * returns the description of the library referenced by this row. + */ + const wxString& GetDescr() const { return description; } + + /** + * Function SetDescr + * changes the description of the library referenced by this row. + */ + void SetDescr( const wxString& aDescr ) { description = aDescr; } + + //---------------------------------------------------------- /** * Function Format @@ -167,49 +196,13 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR ); - /** - * Function SetNickName - * changes the logical name of this library, useful for an editor. - */ - void SetNickName( const wxString& aNickName ) - { - nickName = aNickName; - } - - /** - * Function SetType - * changes the type represented by this record. - */ - void SetType( const wxString& aType ) - { - type = IO_MGR::EnumFromStr( aType ); - } - - /** - * Function SetFullURI - * changes the full URI for the library, useful from a library table editor. - */ - void SetFullURI( const wxString& aFullURI ) - { - uri = aFullURI; - } - - /** - * Function SetOptions - * changes the options string for this record, and is useful from - * the library table editor. - */ - void SetOptions( const wxString& aOptions ) - { - options = aOptions; - } - private: wxString nickName; wxString uri; LIB_T type; wxString options; + wxString description; }; @@ -219,7 +212,7 @@ public: * @a aFallBackTable. Loading of this table fragment is done by using Parse(). * * @param aFallBackTable is another FP_LIB_TABLE which is searched only when - * a record is not found in this table. No ownership is + * a row is not found in this table. No ownership is * taken of aFallBackTable. */ FP_LIB_TABLE( FP_LIB_TABLE* aFallBackTable = NULL ); @@ -249,9 +242,9 @@ public: * *

      * (fp_lib_table
-     *   (lib (name LOGICAL)(type TYPE)(uri FULL_URI)(options OPTIONS))
-     *   (lib (name LOGICAL)(type TYPE)(uri FULL_URI)(options OPTIONS))
-     *   (lib (name LOGICAL)(type TYPE)(uri FULL_URI)(options OPTIONS))
+     *   (lib (name LOGICAL)(descr DESCRIPTION)(uri FULL_URI)(type TYPE)(options OPTIONS))
+     *   (lib (name LOGICAL)(descr DESCRIPTION)(uri FULL_URI)(type TYPE)(options OPTIONS))
+     *   (lib (name LOGICAL)(descr DESCRIPTION)(uri FULL_URI)(type TYPE)(options OPTIONS))
      *  )
      * 
* @@ -363,6 +356,15 @@ public: const ROW* FindRow( const wxString& aNickName ) throw( IO_ERROR ); + /** + * Function ExpandEnvSubsitutions + * replaces any environment variable references with their values and is + * here to fully embellish the ROW::uri in a platform independent way. + * This enables (fp_lib_table)s to have platform dependent environment + * variables in them, allowing for a uniform table across platforms. + */ + static const wxString ExpandSubtitutions( const wxString aString ); + protected: /** diff --git a/include/richio.h b/include/richio.h index 14411aee4d..0a322eca0a 100644 --- a/include/richio.h +++ b/include/richio.h @@ -115,12 +115,7 @@ struct IO_ERROR // : std::exception init( aThrowersFile, aThrowersLoc, wxString( aMsg ) ); } - void init( const char* aThrowersFile, const char* aThrowersLoc, const wxString& aMsg ) - { - errorText.Printf( IO_FORMAT, aMsg.GetData(), - wxString::FromUTF8( aThrowersFile ).GetData(), - wxString::FromUTF8( aThrowersLoc ).GetData() ); - } + void init( const char* aThrowersFile, const char* aThrowersLoc, const wxString& aMsg ); IO_ERROR() {} @@ -165,18 +160,7 @@ struct PARSE_ERROR : public IO_ERROR void init( const char* aThrowersFile, const char* aThrowersLoc, const wxString& aMsg, const wxString& aSource, const char* aInputLine, - int aLineNumber, int aByteIndex ) - { - // save inpuLine, lineNumber, and offset for UI (.e.g. Sweet text editor) - inputLine = aInputLine; - lineNumber = aLineNumber; - byteIndex = aByteIndex; - - errorText.Printf( PARSE_FORMAT, aMsg.GetData(), aSource.GetData(), - aLineNumber, aByteIndex, - wxString::FromUTF8( aThrowersFile ).GetData(), - wxString::FromUTF8( aThrowersLoc ).GetData() ); - } + int aLineNumber, int aByteIndex ); ~PARSE_ERROR() throw ( /*none*/ ){} }; diff --git a/pcbnew/pcb_plot_params.h b/pcbnew/pcb_plot_params.h index bc316d4e59..77d5890788 100644 --- a/pcbnew/pcb_plot_params.h +++ b/pcbnew/pcb_plot_params.h @@ -188,13 +188,13 @@ public: bool operator==( const PCB_PLOT_PARAMS &aPcbPlotParams ) const; bool operator!=( const PCB_PLOT_PARAMS &aPcbPlotParams ) const; - void SetColor( EDA_COLOR_T aVal ) { m_color = aVal; } + void SetColor( EDA_COLOR_T aVal ) { m_color = aVal; } EDA_COLOR_T GetColor() const { return m_color; } - void SetReferenceColor( EDA_COLOR_T aVal ) { m_referenceColor = aVal; } + void SetReferenceColor( EDA_COLOR_T aVal ) { m_referenceColor = aVal; } EDA_COLOR_T GetReferenceColor() const { return m_referenceColor; } - void SetValueColor( EDA_COLOR_T aVal ) { m_valueColor = aVal; } + void SetValueColor( EDA_COLOR_T aVal ) { m_valueColor = aVal; } EDA_COLOR_T GetValueColor() const { return m_valueColor; } void SetTextMode( PlotTextMode aVal ) { m_textMode = aVal; } @@ -292,5 +292,4 @@ public: */ extern int g_DrawDefaultLineThickness; - #endif // PCB_PLOT_PARAMS_H_ diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp index 8930e593dc..6f7ada1238 100644 --- a/pcbnew/pcbnew_config.cpp +++ b/pcbnew/pcbnew_config.cpp @@ -45,6 +45,10 @@ #include #include +#if defined(DEBUG) + #include +#endif + #include #include #include @@ -88,6 +92,39 @@ void PCB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) FP_LIB_TABLE gbl; FP_LIB_TABLE prj; +#if defined(DEBUG) + FP_LIB_TABLE_LEXER glex( + "(fp_lib_table\n" + " (lib (name passives)(descr \"Demo Lib\")(type KiCad)(uri ${KISFP}/passives.pretty))\n" + " (lib (name micros)(descr \"Small stuff\")(type Legacy)(uri ${KISFP}/passives.mod)(options \"op1=2\"))\n" + " (lib (name chips)(descr \"Potatoe chips\")(type Eagle)(uri /opt/eagle-6.2.0/lbr/con-amp-micromatch.lbr))\n" + ")", wxT( "gbl" ) ); + + FP_LIB_TABLE_LEXER plex( + "(fp_lib_table\n" + " (lib (name passives)(descr \"Demo Lib\")(type KiCad)(uri ${KIUFP}/passives.pretty))\n" + " (lib (name micros)(descr \"Small stuff\")(type Legacy)(uri ${KIUFP}/micros.mod)(options \"op1=2\"))\n" + " (lib (name chips)(descr \"Potatoe chips\")(type Eagle)(uri /opt/eagle-6.2.0/lbr/con-amp-micromatch.lbr))\n" + ")", wxT( "prj" ) ); + + try + { + gbl.Parse( &glex ); + prj.Parse( &plex ); + } + /* PARSE_ERROR is an IO_ERROR, handle them the same for now. + catch( PARSE_ERROR pe ) + { + DisplayError( this, pe.errorText ); + break; + } + */ + catch( IO_ERROR ioe ) + { + DisplayError( this, ioe.errorText ); + break; + } +#else gbl.InsertRow( FP_LIB_TABLE::ROW( wxT( "passives" ), wxT( "%G/passives" ), wxT( "KiCad" ), wxT( "speed=fast,purpose=testing" ) ) ); @@ -96,6 +133,7 @@ void PCB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) prj.InsertRow( FP_LIB_TABLE::ROW( wxT( "micros" ), wxT( "%P/potato_chips" ), wxT( "Eagle" ), wxT( "speed=fast,purpose=testing" ) ) ); +#endif int r = InvokePcbLibTableEditor( this, &gbl, &prj );